
Copyright © 1992-2010 Bruno Haible
Copyright © 1998-2010 Sam Steingold
Legal Status of the CLISP Implementation Notes
These notes are dually licensed under GNU FDL and GNU GPL. This means that you can redistribute this document under either of these two licenses, at your choice.
These notes are covered by the GNU FDL. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (FDL), either version 1.2 of the License, or (at your option) any later version published by the Free Software Foundation (FSF); with no Invariant Sections, with no Front-Cover Text, and with no Back-Cover Texts. A copy of the license is included in Appendix B, GNU Free Documentation License.
These notes are covered by the GNU GPL. This document documents free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL), either version 2 of the License, or (at your option) any later version published by the Free Software Foundation (FSF). A copy of the license is included in Appendix C, GNU General Public License.
Abstract
This document describes the GNU CLISP - an implementation of the [ANSI CL standard].
See the section called “Bugs” for instructions on how to report bugs (both in the software and the documentaion).
See Q: A.1.1.5 for information on CLISP support.
Table of Contents
STREAM-EXTERNAL-FORMATSTREAM-ELEMENT-TYPEEXT:MAKE-STREAMFILE-POSITIONEXT:ELASTIC-NEWLINEOPENCLEAR-INPUTCLOSEOPEN-STREAM-PBROADCAST-STREAMEXT:MAKE-BUFFERED-INPUT-STREAM
and EXT:MAKE-BUFFERED-OUTPUT-STREAM
WRITE & WRITE-TO-STRINGPRINT-UNREADABLE-OBJECTList of Figures
List of Tables
EVAL/APPLYTYPECODESHEAPCODESList of Examples
TRACEEXT:FILL-STREAM usagegethostname from CLISPREGEXP:MATCHREGEXP:REGEXP-QUOTEThese notes discuss the CLISP implementation of Common Lisp by and . The current maintainers are and .
This implementation is mostly conforming to the [ANSI CL standard] available on-line as the [Common Lisp HyperSpec] (but the printed ANSI document remains the authoritative source of information). [ANSI CL standard] supersedes the earlier specifications [CLtL1] and [CLtL2].
The first part of these notes, Part I, “Chapters or the Common Lisp HyperSpec”, is indexed in parallel to the [Common Lisp HyperSpec] and documents how CLISP implements the [ANSI CL standard].
The second part, Part II, “Common Portable Extensions”, documents the
common extensions to the [ANSI CL standard], specifically Meta-Object Protocol and “GRAY”
STREAMs.
The third part, Part III, “Extensions Specific to CLISP”, documents the CLISP-specific extensions, e.g., Section 32.4, “Socket Streams”.
The fourth part, Part IV, “Internals of the CLISP Implementation”, is intended mostly
for developers as it documents the CLISP internals, e.g., garbage-collection,
adding new built-ins, and the bytecodes generated by the compiler
(i.e., what is printed by DISASSEMBLE).
The following is the mark-up notations used in this document:
Table 1. Mark-up conventions
| Object Kind | Example |
|---|---|
| Function | CAR |
| Variable | CUSTOM:*LOAD-PATHS* |
| Formal Argument | x |
| Keyword | :EOF |
| Number | 0 |
| Character | #\Newline |
| Class, type | REGEXP:MATCH |
FORMAT instruction | ~A |
| Standard lambda list keyword | &KEY |
| Declaration | FTYPE |
| Package | “COMMON-LISP-USER” |
| Real file | config.lisp |
| Abstract file | #P".c" |
| Code (you are likely to type it) | ( |
| Data (CLISP is likely to print it) | #(1 2 3) |
| Program listing | ( |
| Bytecode instruction | (STOREV |
| First mention of an entity | firstterm |
| External module | libsvm, bindings/glibc |
| Command line argument | -x |
| Interaction | Computer output |
Table of Contents
STREAM-EXTERNAL-FORMATSTREAM-ELEMENT-TYPEEXT:MAKE-STREAMFILE-POSITIONEXT:ELASTIC-NEWLINEOPENCLEAR-INPUTCLOSEOPEN-STREAM-PBROADCAST-STREAMEXT:MAKE-BUFFERED-INPUT-STREAM
and EXT:MAKE-BUFFERED-OUTPUT-STREAM
WRITE & WRITE-TO-STRINGPRINT-UNREADABLE-OBJECTTable of Contents
The final delimiter of an interactive stream:
This final delimiter is never actually seen by programs; no need to
test for #\^D or #\^Z - use
READ-CHAR-NO-HANG to check for end-of-stream.
A newline character can be entered by the user by pressing the Enter key.
See also Section 21.13, “Function CLEAR-INPUT”.
Safety settings are ignored by the interpreted code;
therefore where the standard uses the phrase “should signal an
error”, an ERROR is SIGNALed.
See Section 3.3.4, “Declaration SAFETY” for the safety of compiled code.
All 978 symbols in the “COMMON-LISP” package specified by the [ANSI CL standard] are implemented.
Table of Contents
The standard characters are #\Newline and the
graphic characters
with a CODE-CHAR between 32 and 126 (inclusive).
The requirement of step 4 that a “reader
macro function may return zero values or one value”
is enforced. You can use the function VALUES to control the
number of values returned.
A reserved token
,
i.e., a token that has
potential number syntax but cannot be
interpreted as a NUMBER, is interpreted as SYMBOL when being
read.
When a token with package markers is read, then no checking is
done whether the SYMBOL-PACKAGE part and the SYMBOL-NAME part do
not have number syntax. (What would the purpose of this check be?)
So we consider tokens like USER:: or :1 or
LISP::4711 or 21:3 as symbols.
The backquote read macro also works when nested. Example:
(EVAL``(,#'(LAMBDA() ',a) ,#'(LAMBDA() ',b))) ≡ (EVAL`(list #'(LAMBDA() ',a) #'(LAMBDA() ',b))) ≡ (EVAL(list 'list (list 'function (list 'lambda nil (list 'quote a))) (list 'function (list 'lambda nil (list 'quote b)))))
Reader macros are also defined for the following:
Additional reader macros
#,#YFUNCTION objects and input STREAM's EXT:ENCODINGs
#""PATHNAME: #"test.lisp"
is the value of (PATHNAME "test.lisp")#\Code allows input of characters of arbitrary code:
e.g., #\Code231 reads as the character
(.CODE-CHAR 231)
This is the list of objects whose external representation cannot be meaningfully read in:
Unreadable objects
#<type ...>STRUCTURE-OBJECTs lacking a keyword
constructor#<ARRAY type
dimensions>ARRAYs except STRINGs, if
*PRINT-ARRAY* is NIL#<SYSTEM-FUNCTION name>#<ADD-ON-SYSTEM-FUNCTION
name>#<SPECIAL-OPERATOR
name>#<COMPILED-FUNCTION
name>CUSTOM:*PRINT-CLOSURE* is NIL
#<FUNCTION name ...>CUSTOM:*PRINT-CLOSURE* is NIL
#<FRAME-POINTER #x...>#<DISABLED POINTER>BLOCK or TAGBODY#<...STREAM...>STREAM#<PACKAGE name>PACKAGE#<HASH-TABLE #x...>HASH-TABLE, if *PRINT-ARRAY* is NIL
#<READTABLE #x...>READTABLE#<SYMBOL-MACRO form>SYMBOL-MACRO handler#<MACRO function>DEFMACRO and friends)
#<FFI:FOREIGN-POINTER
#x...>#<FFI:FOREIGN-ADDRESS
#x...>#<FFI:FOREIGN-VARIABLE name
#x...>#<FFI:FOREIGN-FUNCTION name
#x...>#<UNBOUND>#<SPECIAL REFERENCE>SPECIAL
#<DOT>READ result for “.”
#<END OF FILE>READ result, when the end-of-stream is reached
#<READ-LABEL ...>READ result for #n#
#<ADDRESS #x...>#<SYSTEM-POINTER #x...>Table of Contents
All the functions built by FUNCTION, COMPILE and the like are
atoms. There are built-in functions written in C, compiled
functions (both of type COMPILED-FUNCTION) and interpreted
functions (of type FUNCTION).
Table 3.1. Function call limits
CALL-ARGUMENTS-LIMIT | 212=4096 |
MULTIPLE-VALUES-LIMIT | 27=128 |
LAMBDA-PARAMETERS-LIMIT | 212=4096 |
Macro EXT:THE-ENVIRONMENT. As in Scheme, the macro (
returns the current lexical environment. This works only in interpreted code and
is not compilable!EXT:THE-ENVIRONMENT)
Function (EXT:EVAL-ENV
. evaluates a form in a given lexical environment, just as if the
form had been a part of the program that the form &OPTIONAL environment)environment came from.
DEFINE-SYMBOL-MACROThe macro DEFINE-SYMBOL-MACRO establishes SYMBOL-MACROs with
global scope (as opposed to SYMBOL-MACROs defined with
SYMBOL-MACROLET, which have local scope).
The function
EXT:SYMBOL-MACRO-EXPAND
tests for a SYMBOL-MACRO: If symbol is defined as a SYMBOL-MACRO
in the global environment, ( returns two
values, EXT:SYMBOL-MACRO-EXPAND symbol)T and the expansion; otherwise it returns NIL.
EXT:SYMBOL-MACRO-EXPAND is a special case of MACROEXPAND-1. MACROEXPAND-1
can also test whether a symbol is defined as a SYMBOL-MACRO in lexical environments
other than the global environment.
“Undefined variables”, i.e. variables which are
referenced outside any lexical binding for a variable of the same name
and which are not declared SPECIAL, are treated like dynamic variables
in the global environment. The compiler SIGNALs a WARNING when it
encounters an undefined variable.
Lists of the form (( are also
treated as function forms. This makes the syntax
SETF symbol) ...)( consistent with the syntax
function-name arguments ...)(.
It implements the item 7 of the [ANSI CL standard] issue FUNCTION-NAME:LARGE and the
definition of function forms,
and is consistent with the use of function names elsewhere in Common Lisp.
FUNCALL #'function-name arguments ...)
EVAL-WHENEVAL-WHEN also accepts the situations (NOT EVAL)
and (NOT COMPILE).
The situations EVAL,
LOAD and COMPILE are
deprecated by the [ANSI CL standard], and they are not equivalent to the new
standard situations :EXECUTE,
:LOAD-TOPLEVEL
and :COMPILE-TOPLEVEL in that they ignore the
top-level form versus non-top-level form distinction.
THEThe special form ( is
similar to THE value-type form)CHECK-TYPE but does a type check only in interpreted
code (no type check is done in compiled code - but see the EXT:ETHE
macro) and does not allow interactive error correction by the user.
Constant LAMBDA-LIST-KEYWORDS. (&OPTIONAL &REST &KEY &ALLOW-OTHER-KEYS
&AUX &BODY &WHOLE &ENVIRONMENT)
SYMBOL-FUNCTION(
requires SETF (SYMBOL-FUNCTION symbol) object)object to be either a FUNCTION, a SYMBOL-FUNCTION
return value, or a lambda expression. The lambda expression is thereby
immediately converted to a FUNCTION.
DEFUN and DEFMACRO are allowed in non-toplevel positions. As
an example, consider the old ([CLtL1]) definition of GENSYM:
(let ((gensym-prefix "G")
(gensym-count 1))
(defun gensym (&optional (x nil s))
(when s
(cond ((stringp x) (setq gensym-prefix x))
((integerp x)
(if (minusp x)
(error "~S: index ~S is negative" 'gensym x)
(setq gensym-count x)))
(t (error "~S: argument ~S of wrong type" 'gensym x))))
(prog1
(make-symbol
(concatenate 'string
gensym-prefix
(write-to-string gensym-count :base 10 :radix nil)))
(incf gensym-count))))
See also Section 3.2.2.2, “Minimal Compilation ”.
Function EXT:ARGLIST. Function ( returns the lambda list of
the function or macro that EXT:ARGLIST name)name names and SIGNALs an ERROR if name is
not FBOUNDP. It also SIGNALs an ERROR when the macro lambda list is not
available due to the compiler optimization settings
(see Section 3.3.6, “Declaration SPACE”).
Variable CUSTOM:*SUPPRESS-CHECK-REDEFINITION*. When CUSTOM:*SUPPRESS-CHECK-REDEFINITION* is NIL,
CLISP issues a WARNING when a function (macro, variable, class,
etc) is redefined in a different file than its original definition.
It is not a good idea to set this variable to T.
Variable CUSTOM:*DEFUN-ACCEPT-SPECIALIZED-LAMBDA-LIST*. When CUSTOM:*DEFUN-ACCEPT-SPECIALIZED-LAMBDA-LIST* is
non-NIL, DEFUN accepts specialized lambda lists, converting type-parameter
associations to type declarations:
(defun f ((x list) (y integer)) ...)
is equivalent to
(defun f (x y) (declare (type list x) (type integer y)) ...)
This extension is disabled by -ansi and by setting CUSTOM:*ANSI* to T,
but can be re-enabled by setting CUSTOM:*DEFUN-ACCEPT-SPECIALIZED-LAMBDA-LIST* explicitly.
Compiler macros are expanded in the compiled code only, and ignored by the interpreter.
When a DEFUN form is EVALuated, the macros used there are
expanded, so they must be already defined, and their (re)definition
does not affect functions which are already defined.
This means that even the interpreted code is minimally compiled in CLISP.
Non-conforming code that does not follow the rule
“Special proclamations for dynamic variables must be made in the compilation environment.”
can produce quite unexpected results, e.g., observable differences between compiled and interpreted programs:
(defun adder-c (value) (declare(COMPILE)) (lambda (x) (+ x value))) ⇒ADDER-C; compiled function;valueis lexical (defun adder-i (value) (lambda (x) (+ x value))) ⇒ADDER-I; interpreted function;valueis lexical (defparameter add-c-10 (adder-c 10)) ⇒ADD-C-10; compiled function (defparameter add-i-10 (adder-i 10)) ⇒ADD-I-10; interpreted function (funcall add-c-10 32) ⇒42; as expected (funcall add-i-10 32) ⇒42; as expected (defvar value 12) ⇒VALUE; affectsADDER-IandADD-I-10but notADDER-CandADD-C-10(funcall add-c-10 32) ⇒42; as before (funcall add-i-10 32) ⇒44;valueis now dynamic!
Non-conformance. The code shown above has a SPECIAL proclamation (by DEFVAR)
for the variable value in the execution environment
(before the last two FUNCALLs)
but not in the compilation environment: at the moment
the ADDER-I function is defined,
value is not known to be a SPECIAL variable.
Therefore the code is not conforming.
The function ADD-C-10 was compiled before
value was declared SPECIAL, so the symbol value was
eliminated from its code and the SPECIAL declaration did
not affect the return value (i.e., (funcall
add-c-10 32) always returned 42).
On the opposite, function ADDER-I was not
compiled, so ADD-I-10
was interpreted.
Whenever ADD-I-10 is executed, its definition is
interpreted all over again. Before DEFVAR, value is evaluated as
a lexical (because is is not declared SPECIAL yet), but after
DEFVAR, we see a globally SPECIAL symbol value which
can have only a global SYMBOL-VALUE (not a local binding), and thus
we are compelled to evaluate it to 12.
This behavior was implemented intentionally to ease interactive
development, because usually
the ADDER-I above would be followed by a
(forgotten) DEFVAR.
When a user compiles a program, the compiler is allowed to
remember the information whether a variable was SPECIAL or not,
because that allows the compiler to generate more efficient code,
but in interpreted code, when the user changes the state of a variable,
he does not want to re-evaluate all DEFUNs that use the variable.
[ANSI CL standard] gives the implementation freedom regarding interpreted evaluation, how much it wants to remember / cache, and how much it wants to re-evaluate according the current environment, if it has changed. CLISP implements ad-hoc look-up for variables (but not for macros, see Section 3.2.2.2, “Minimal Compilation ”).
Hash tables are externalizable objects.
Both COMPILE and EVAL may SIGNAL the EXT:SOURCE-PROGRAM-ERROR
CONDITION which derives from PROGRAM-ERROR and which contains
additional slots with accessors
EXT:SOURCE-PROGRAM-ERROR-FORMERROR was
SIGNALedEXT:SOURCE-PROGRAM-ERROR-DETAILERRORThe declarations (,
TYPE type variable ...)(,
are ignored by both the interpreter and the compiler.FTYPE type function ...)
SPECIALDeclaration EXT:NOTSPECIAL. Declarations (
and PROCLAIM '(SPECIAL variable))DEFCONSTANT are undone by the ( declaration. This declaration can be used only in
global PROCLAIM '(EXT:NOTSPECIAL
variable))PROCLAIM and DECLAIM forms, not in local DECLARE forms.
You cannot expect miracles: functions compiled before
the EXT:NOTSPECIAL proclamation was issued will still be treating variable as
special even after the EXT:NOTSPECIAL proclamation. See also
Section 3.2.2.3, “Semantic Constraints ”.
Function EXT:SPECIAL-VARIABLE-P. You can use the function ( to check whether the EXT:SPECIAL-VARIABLE-P symbol
&OPTIONAL environment)symbol is a
dynamic variable. environment of NIL or omitted means use the global environment.
You can also obtain the current lexical environment using the macro
EXT:THE-ENVIRONMENT (interpreted code only).
This function will always return T for global special
variables and constant variables.
EXT:CONSTANT-NOTINLINEConstants defined by DEFCONSTANT but proclaimed EXT:CONSTANT-NOTINLINE
will not be inlined by the compiler. This is useful for variables
which remain constant within an a single Lisp process but may vary
between processes and machines (such as endianness or word size) thus
they should be written to #P".fas"s as symbols, not values.
CONSTANTPFunction CONSTANTP fully complies with [ANSI CL standard].
Additionally, some non-trivial forms are identified as constants, e.g.,
( returns CONSTANTP '(+ 1 2 3))T.
Since DEFCONSTANT initial value forms are not
evaluated at compile time, CONSTANTP will not report T of their
name within the same compilation unit for the null lexical environment.
This is consistent and matches questionable code using the pattern
(.
Use IF (CONSTANTP form) (EVAL form))EVAL-WHEN if you need recognition and the value during
compile-time. See also Section 31.11.5, “Macro EXT:COMPILE-TIME-VALUE”.
SAFETYDeclaration (
results in “safe” compiled code: function calls are never
eliminated. This guarantees the semantics described in
[sec_3-5].
OPTIMIZE (SAFETY 3))
(COMPILE)The declaration (COMPILE) has the effect that the current
form is compiled prior to execution. Examples:
(LOCALLY(DECLARE(compile))form)
executes the compiled version of form.
(LET((x 0)) (FLET((inc () (DECLARE(compile)) (INCFx)) (dec () (DECFx))) (VALUES#'inc #'dec)))
returns two functions. The first is compiled and increments x, the
second is interpreted (slower) and decrements the same x.
This declaration can also be used to name the resulting compiled closure:
(LAMBDA(x) (DECLARE(compile ident)) x) ⇒(#<COMPILED-FUNCTIONIDENT>FUNCTION-LAMBDA-EXPRESSION*) ⇒; source is not preserved ⇒NIL⇒TIDENT(FBOUNDP'ident) ⇒; sic!NIL
SPACEThe declaration determines what metadata is recorded in the function object:
The initial value of an &AUX variable in a boa lambda list is
the value of the corresponding slot's initial form.
Table of Contents
The general form of the COMPLEX type specifier is (.
The type specifier COMPLEX type-of-real-part
type-of-imaginary-part)(
is equivalent to COMPLEX type)(.COMPLEX type
type)
DEFTYPE lambda lists are subject to destructuring (nested lambda lists
are allowed, as in DEFMACRO) and may contain a &WHOLE marker,
but not an &ENVIRONMENT marker.
Function (. If EXT:TYPE-EXPAND
type &OPTIONAL once-p)type is a user-defined type specifier this will expand it
recursively until it is no longer a user-defined type
(unless once-p is supplied and non-NIL).
Two values are returned - the expansion and an indicator (T or NIL)
of whether the original type was a user-defined type specifier.
The possible results of TYPE-OF
CONSSYMBOL, NULL, BOOLEAN,
KEYWORDBIT, (INTEGER 0
#.MOST-POSITIVE-FIXNUM),
(INTEGER
#.MOST-NEGATIVE-FIXNUM (0)),
(INTEGER
(#.MOST-POSITIVE-FIXNUM)),
(INTEGER *
(#.MOST-NEGATIVE-FIXNUM))RATIONAL, SHORT-FLOAT, SINGLE-FLOAT,
DOUBLE-FLOAT, LONG-FLOAT, COMPLEXCHARACTER, BASE-CHAR,
STANDARD-CHAR(ARRAY element-type
dimensions), (SIMPLE-ARRAY
element-type dimensions)(VECTOR T
size), (SIMPLE-VECTOR
size)(STRING
size), (SIMPLE-STRING
size)(BASE-STRING
size), (SIMPLE-BASE-STRING
size)(BIT-VECTOR
size), (SIMPLE-BIT-VECTOR
size)FUNCTION, COMPILED-FUNCTION,
STANDARD-GENERIC-FUNCTIONSTREAM, FILE-STREAM, SYNONYM-STREAM,
BROADCAST-STREAM, CONCATENATED-STREAM, TWO-WAY-STREAM,
ECHO-STREAM, STRING-STREAMPACKAGE, HASH-TABLE, READTABLE, PATHNAME,
LOGICAL-PATHNAME, RANDOM-STATE, BYTESPECIAL-OPERATOR,
LOAD-TIME-EVAL, SYMBOL-MACRO,
GLOBAL-SYMBOL-MACRO, EXT:ENCODING,
FFI:FOREIGN-POINTER, FFI:FOREIGN-ADDRESS, FFI:FOREIGN-VARIABLE,
FFI:FOREIGN-FUNCTIONEXT:WEAK-POINTER, EXT:WEAK-LIST, EXT:WEAK-AND-RELATION,
EXT:WEAK-OR-RELATION, EXT:WEAK-MAPPING, EXT:WEAK-AND-MAPPING,
EXT:WEAK-OR-MAPPING, EXT:WEAK-ALIST,
READ-LABEL,
FRAME-POINTER,
SYSTEM-INTERNALADDRESS (should not
occur)SYMBOL (structure types or CLOS
classes)Function COERCE. FIXNUM is not a character
designator in [ANSI CL standard], although CODE-CHAR provides an
obvious venue to COERCE a FIXNUM to a CHARACTER.
When CUSTOM:*COERCE-FIXNUM-CHAR-ANSI* is NIL, CLISP COERCEs FIXNUMs to
CHARACTERs via CODE-CHAR.
When CUSTOM:*COERCE-FIXNUM-CHAR-ANSI* is non-NIL, FIXNUMs cannot be
COERCEd to CHARACTERs.
The CLOS symbols are EXPORTed from the package “CLOS”.
“COMMON-LISP” uses (as in USE-PACKAGE) “CLOS” and EXT:RE-EXPORTs the
[ANSI CL standard] standard exported symbols (the CLISP extensions, e.g.,
those described in Chapter 29, Meta-Object Protocol, are not EXT:RE-EXPORTed).
Since the default :USE argument
to MAKE-PACKAGE is “COMMON-LISP”, the standard CLOS symbols are normally
visible in all user-defined packages.
If you do not want them (for example, if you want to use the
PCL
implementation of CLOS instead of the native one), do the following:
(DEFPACKAGE"CL-NO-CLOS" (:use "CL")) (DO-EXTERNAL-SYMBOLS(symbol“COMMON-LISP”) (SHADOWsymbol"CL-NO-CLOS")) (DO-SYMBOLS(symbol"CL-NO-CLOS") (EXPORTsymbol"CL-NO-CLOS")) (IN-PACKAGE"CL-NO-CLOS") (LOAD"pcl") ; or whatever (DEFPACKAGE"MY-USER" (:use "CL-NO-CLOS")) (IN-PACKAGE"MY-USER") ;; your code which uses PCL goes here
DEFCLASS supports the option :METACLASS STRUCTURE-CLASS.
This option is necessary in order to define a subclass of a
DEFSTRUCT-defined structure type using DEFCLASS instead of
DEFSTRUCT.
When CALL-NEXT-METHOD is called with arguments, the rule that
the ordered set of applicable methods must be the same as for the
original arguments is enforced by the implementation only in
interpreted code.
CLOS:GENERIC-FLET and
CLOS:GENERIC-LABELS
are implemented as macros, not as special operators (as permitted by
[sec_3-1-2-1-2-2]).
They are not imported into the packages “COMMON-LISP-USER” and “COMMON-LISP” because
of the [ANSI CL standard] issue GENERIC-FLET-POORLY-DESIGNED:DELETE.
PRINT-OBJECT is only called on objects of type
STANDARD-OBJECT and STRUCTURE-OBJECT.
It is not called on other objects, like CONSes
and NUMBERs, due to the performance concerns.
Among those classes listed in Figure
4-8, only the following are instances of BUILT-IN-CLASS:
TCHARACTERNUMBER, COMPLEX, REAL, FLOAT,
RATIONAL, RATIO, INTEGERSEQUENCEARRAY, VECTOR, BIT-VECTOR,
STRINGLIST, CONSSYMBOL, NULLFUNCTIONHASH-TABLEPACKAGEPATHNAME, LOGICAL-PATHNAMERANDOM-STATEREADTABLESTREAM, BROADCAST-STREAM,
CONCATENATED-STREAM, ECHO-STREAM, STRING-STREAM,
FILE-STREAM, SYNONYM-STREAM, TWO-WAY-STREAM
DEFCLASS supports the :METACLASS option. Possible values are
STANDARD-CLASS (the default), STRUCTURE-CLASS (which creates
structure classes, like DEFSTRUCT does), and user-defined
meta-classes (see Section 29.3.6.7, “Generic Function CLOS:VALIDATE-SUPERCLASS”).
It is not required that the superclasses of a class are
defined before the DEFCLASS form for the class is evaluated.
Use Meta-Object Protocol generic functions CLOS:CLASS-FINALIZED-P to check whether the
class has been finalized and thus its instances can be created,
and CLOS:FINALIZE-INHERITANCE to force class finalization.
See also Section 29.3.1, “Macro DEFCLASS”.
Trivial changes, e.g., those that can occur when doubly loading
the same code, do not require updating the instances.
These are the changes that do not modify the set of local slots
accessible in instances, e.g., changes to slot options :INITFORM,
:DOCUMENTATION, and changes to class options
:DEFAULT-INITARGS, :DOCUMENTATION.
The instances are updated when they are first accessed, not at
the time when the class is redefined or MAKE-INSTANCES-OBSOLETE is
called. When the class has been redefined several times since the
instance was last accessed, UPDATE-INSTANCE-FOR-REDEFINED-CLASS is
still called just once.
Table of Contents
&KEY markers in DEFSETF lambda lists are supported, but the
corresponding keywords must appear literally in the program text.
An attempt to modify read-only data SIGNALs an ERROR.
Program text and quoted constants loaded from files are considered
read-only data. This check is only performed for strings, not for
conses, other kinds of arrays, and user-defined data types.
(,
GET-SETF-EXPANSION form &OPTIONAL environment)(EXT:GET-SETF-METHOD , and
form &OPTIONAL environment)(EXT:GET-SETF-METHOD-MULTIPLE-VALUE receive as optional argument form &OPTIONAL
environment)environment the environment
necessary for macro expansions. In DEFINE-SETF-EXPANDER
and EXT:DEFINE-SETF-METHOD lambda lists, one can
specify &ENVIRONMENT and a variable, which will be bound to the
environment. This environment should be passed to all calls of
GET-SETF-EXPANSION, EXT:GET-SETF-METHOD and
EXT:GET-SETF-METHOD-MULTIPLE-VALUE. If this is
done, even local macros will be interpreted as places correctly.
Additional places:
FUNCALL(SETF (FUNCALL #'symbol ...)
object) and
(SETF (FUNCALL 'symbol ...) object)
are equivalent to (SETF (symbol ...) object).
PROGN(SETF (PROGN form ... place)
object)LOCALLY(SETF (LOCALLY declaration ...
form ... place) object)
IF(SETF (IF condition
place1
place2)
object)GET-DISPATCH-MACRO-CHARACTER(SETF (GET-DISPATCH-MACRO-CHARACTER ...)
...) calls SET-DISPATCH-MACRO-CHARACTER.
EXT:LONG-FLOAT-DIGITS:(SETF (EXT:LONG-FLOAT-DIGITS) digits) sets the
default mantissa length of LONG-FLOATs to digits bits.
VALUES-LIST(
is equivalent to SETF (VALUES-LIST list) form)(.VALUES-LIST (SETF list
(MULTIPLE-VALUE-LIST form)))
FUNCTION-LAMBDA-EXPRESSIONThe name of a FFI:FOREIGN-FUNCTION is a string
(the name of the underlying C function), not a lisp function name.
DESTRUCTURING-BINDThis macro does not perform full error checking.
PROG1, PROG2, AND,
OR, PSETQ, WHEN, UNLESS, COND, CASE, MULTIPLE-VALUE-LIST,
MULTIPLE-VALUE-BIND, MULTIPLE-VALUE-SETQThese macros are implemented as special operators (as permitted by [sec_3-1-2-1-2-2]) and, as such, are rather efficient.
DEFCONSTANTThe initial value is not evaluated at compile time,
just like with DEFVAR and DEFPARAMETER.
Use EVAL-WHEN if you need the value at compile time.
constant variables may not be bound dynamically or lexically.
See also Section 3.3.2, “Declaration EXT:CONSTANT-NOTINLINE”.
If you need to undo the effects of a DEFCONSTANT form,
PROCLAIM the symbol SPECIAL (to turn the constant variable into a dynamic variable),
and then PROCLAIM it EXT:NOTSPECIAL (to turn the dynamic variable into a lexical variable).
If you follow the usual variable naming convention
(*FOO* for DEFVAR and DEFPARAMETER,
+BAR+ for DEFCONSTANT, ZOT
for LET/LET*), you will save yourself a lot of trouble.
See also Q: A.4.14.
CUSTOM:*SUPPRESS-SIMILAR-CONSTANT-REDEFINITION-WARNING*If the variable being defined by DEFCONSTANT is already bound to
a value which is not EQL to the new value, a WARNING is issued.
If, however, the new value is visually similar
(prints to the same string, as is commonly the case when re-loading files)
to the old one, the warning can be suppressed by setting
CUSTOM:*SUPPRESS-SIMILAR-CONSTANT-REDEFINITION-WARNING* to a non-NIL value.
The initial value of CUSTOM:*SUPPRESS-SIMILAR-CONSTANT-REDEFINITION-WARNING* is NIL.
EXT:FCASEThis macro allows specifying the test for CASE, e.g.,
(fcase string= (subseq foo 0 (position #\Space foo))
("first" 1)
(("second" "two") 2)
(("true" "yes") t)
(otherwise nil))
is the same as
(let ((var (subseq foo 0 (position #\Space foo))))
(cond ((string= var "first") 1)
((or (string= var "second") (string= var "two")) 2)
((or (string= var "true") (string= var "yes")) t)
(t nil)))
If you use a built-in HASH-TABLE test (see Section 18.4, “Function HASH-TABLE-TEST”)
as the test (e.g., EQUAL instead of STRING= above, but not a test
defined using EXT:DEFINE-HASH-TABLE-TEST), the compiler will be able to optimize the
EXT:FCASE form better than the corresponding COND form.
This function checks that exactly one of its arguments is non-NIL
and, if this is the case, returns its value and index in the argument
list as multiple values, otherwise returns NIL.
EQEQ compares CHARACTERs and FIXNUMs as EQL does.
No unnecessary copies are made of CHARACTERs and NUMBERs.
Nevertheless, one should use EQL as it is more portable across Common Lisp
implementations.
( always
returns LET ((x y)) (EQ x x))T for any Lisp object y.
See also Equality of foreign values.
FUNCTION( returns the local function
definition established by FUNCTION symbol)FLET or LABELS, if it exists, otherwise
the global function definition.
( returns SPECIAL-OPERATOR-P symbol)NIL or
T. If it returns T, then ( returns the (useless) special operator handler.SYMBOL-FUNCTION
symbol)
Table of Contents
Mixing termination test clauses with different default return values is not allowed because it is not specifed whether
(loop repeat 1 thereis nil never nil)
should return T (the default return value
from NEVER) of NIL (the default return value from
THEREIS).
The standard is unambiguous in that the iteration variables do
still exist in the
FINALLY
clause, but not as to what values these variables might have.
Therefore the code which relies on the values of such variables, e.g.,
(loop for x on y finally (return x))
is inherently non-portable across Common Lisp implementations, and should be avoided.
There have been some tightening in the LOOP syntax between
[CLtL2] and [ANSI CL standard], e.g., the following form is legal in the
former but not the latter:
(loop initially for i from 1 to 5 do (print i) finally return i)
When CUSTOM:*LOOP-ANSI* is NIL, such forms are still
accepted in CLISP but elicit a warning at macro-expansion time.
When CUSTOM:*LOOP-ANSI* is non-NIL, an ERROR is SIGNALed.
Table of Contents
Generic function
CLOS:NO-PRIMARY-METHOD
(similar to NO-APPLICABLE-METHOD) is called when there is an
applicable method but no applicable primary
method.
The default methods for CLOS:NO-PRIMARY-METHOD, NO-APPLICABLE-METHOD and
NO-NEXT-METHOD SIGNAL an ERROR of type
CLOS:METHOD-CALL-ERROR
.
You can find out more information about the error using functions
CLOS:METHOD-CALL-ERROR-GENERIC-FUNCTION,
CLOS:METHOD-CALL-ERROR-ARGUMENT-LIST, and
(only for NO-NEXT-METHOD)
CLOS:METHOD-CALL-ERROR-METHOD.
Moreover, when the generic function has only one dispatching
argument, (i.e., such an argument that not all the
corresponding parameter specializers are T), an ERROR of type
CLOS:METHOD-CALL-TYPE-ERROR
is SIGNALed, additionally making TYPE-ERROR-DATUM and
TYPE-ERROR-EXPECTED-TYPE available.
Table of Contents
DEFSTRUCTThe :PRINT-FUNCTION option should contain a lambda expression
(
This lambda expression names a LAMBDA (object stream depth) (declare (ignore depth)) ...)FUNCTION whose task is to output the
external representation of the STRUCTURE-OBJECT object onto the
STREAM stream. This may be done by outputting text onto the
stream using WRITE-CHAR, WRITE-STRING, WRITE, PRIN1, PRINC,
PRINT, PPRINT, FORMAT and the like.
The following rules must be obeyed:
*PRINT-ESCAPE* must be
respected.*PRINT-PRETTY* is up to you.
*PRINT-CIRCLE* need not be
respected. This is managed by the system. (But the print-circle
mechanism handles only those objects that are direct or indirect
components of the structure.)*PRINT-LEVEL* is respected by
WRITE, PRIN1, PRINC, PRINT, PPRINT, FORMAT instructions
~A, ~S, ~W, and FORMAT instructions
~R, ~D, ~B, ~O, ~X, ~F,
~E, ~G, ~$ with not-numerical arguments.
Therefore the print-level mechanism works automatically if only these
functions are used for outputting objects and if they are not called
on objects with nesting level > 1. (The print-level mechanism does
not recognize how many parentheses you have output. It only counts how
many times it was called recursively.)*PRINT-LENGTH* must be respected,
especially if you are outputting an arbitrary number of components.
*PRINT-READABLY* must be
respected. Remember that the values of *PRINT-ESCAPE*,
*PRINT-LEVEL*, *PRINT-LENGTH* are ignored if
*PRINT-READABLY* is true. The value of *PRINT-READABLY* is
respected by PRINT-UNREADABLE-OBJECT, WRITE, PRIN1, PRINC,
PRINT, PPRINT, FORMAT instructions ~A, ~S,
~W, and FORMAT instructions ~R, ~D,
~B, ~O, ~X, ~F, ~E,
~G, ~$ with not-numerical arguments. Therefore
*PRINT-READABLY* will be respected automatically if only these
functions are used for printing objects.*PRINT-BASE*, *PRINT-RADIX*, *PRINT-CASE*,
*PRINT-GENSYM*, *PRINT-ARRAY*, CUSTOM:*PRINT-CLOSURE*,
CUSTOM:*PRINT-RPARS*, CUSTOM:*PRINT-INDENT-LISTS*.The :INHERIT option is exactly like :INCLUDE except that it
does not create new accessors for the inherited slots (this is a
CLISP extension).
The following functions accept a structure name as the only argument.
If DEFSTRUCT was given the :TYPE option (i.e., DEFSTRUCT did
not define a new type), then (
fails (and the regular CLOS Meta-Object Protocol is not applicable), but these
functions still work.FIND-CLASS name)
EXT:STRUCTURE-SLOTSLIST of effective slot definition metaobjects.
EXT:STRUCTURE-DIRECT-SLOTSLIST of direct slot definition metaobjects.
EXT:STRUCTURE-KEYWORD-CONSTRUCTORSYMBOL) of the keyword
constructor function for the structure, or NIL if the structure has
no keyword constructor.EXT:STRUCTURE-BOA-CONSTRUCTORSLIST of names (SYMBOLs)
of BOA constructors for the structure.EXT:STRUCTURE-COPIERSYMBOL) of the copier for the
structure.EXT:STRUCTURE-PREDICATESYMBOL) of the predicate for
the structure.Table of Contents
When an error occurred, you are in a break loop. You can evaluate forms as usual. The help command (or help key if there is one) lists the available debugger commands.
The error message prefix for the first line is “*** - ”.
All subsequent lines are indented by 6 characters.
Long lines are broken on whitespace
(see Section 30.8, “Class EXT:FILL-STREAM”).
Contrary to the recommendation of the standard, CLISP usually
does print the name of the containing function to simplify debugging
in batch mode, see EXT:EXIT-ON-ERROR.
Macro RESTART-CASE. In (,
the argument list can also be specified after the keyword/value pairs
instead of before them, i.e., each RESTART-CASE form {restart-clause}*)restart-clause can be either
(
or restart-name EXT:*ARGS*
{keyword-value-pair}* {form}*)(.
restart-name
{keyword-value-pair}* EXT:*ARGS* {form}*)
Macro EXT:WITH-RESTARTS. The macro EXT:WITH-RESTARTS is like RESTART-CASE, except that the
forms are specified after the restart clauses instead of before them,
and the restarts created are not implicitly associated with any CONDITION.
( is
therefore equivalent to EXT:WITH-RESTARTS ({restart-clause}*) {form}*)(.RESTART-CASE (PROGN {form}*)
{restart-clause}*)
Function COMPUTE-RESTARTS. COMPUTE-RESTARTS and FIND-RESTART behave as specified in
[ANSI CL standard]: If the optional condition argument is non-NIL,
only RESTARTs associated with that CONDITION
and RESTARTs associated with no CONDITION at all are considered.
Therefore the effect of associating a restart to a condition is not to
activate it, but to hide it from other conditions.
This makes the syntax-dependent implicit association performed by
RESTART-CASE nearly obsolete.
Macro EXT:MUFFLE-CERRORS. The macro (
executes the EXT:MUFFLE-CERRORS {form}*)forms; when a continuable ERROR occurs whose CONTINUE RESTART
can be invoked non-interactively (this includes all continuable ERRORs signaled
by the function CERROR), no message is printed, instead, the CONTINUE
RESTART is invoked.
Macro EXT:APPEASE-CERRORS. The macro (
executes the EXT:APPEASE-CERRORS {form}*)forms; when a continuable ERROR occurs whose CONTINUE RESTART
can be invoked non-interactively (this includes all continuable ERRORs SIGNALed
by the function CERROR), it is reported as a WARNING, and the
CONTINUE RESTART is invoked.
Macro EXT:ABORT-ON-ERROR. The macro (
executes the EXT:ABORT-ON-ERROR {form}*)forms; when an ERROR occurs, or when a Control+C
interrupt occurs, the error message is printed and the ABORT
RESTART is invoked.
Macro EXT:EXIT-ON-ERROR. The macro (
executes the EXT:EXIT-ON-ERROR {form}*)forms; when an ERROR occurs, or when a Control+C
interrupt occurs, the error message is printed and CLISP terminates
with an error status.
Variable CUSTOM:*REPORT-ERROR-PRINT-BACKTRACE*. When this variable is non-NIL the error message printed by
EXT:ABORT-ON-ERROR and EXT:EXIT-ON-ERROR includes the backtrace (stack).
Function EXT:SET-GLOBAL-HANDLER. The function (
establishes a global handler for the EXT:SET-GLOBAL-HANDLER condition handler)condition.
The handler should be FUNCALLable (a
SYMBOL or a FUNCTION).
If it returns, the next applicable handler is invoked, so if you do
not want to land in the debugger, it should not return.
E.g., the option -on-error abort and the macro
EXT:ABORT-ON-ERROR are implemented by installing the following handler:
(defun sys::abortonerror (condition) (sys::report-error condition) (INVOKE-RESTART(FIND-RESTART'ABORTcondition)))
When handler is NIL, the handler
for condition is removed and returned.
When condition is also NIL, all global handlers are removed and returned
as a LIST, which can then be passed to EXT:SET-GLOBAL-HANDLER as the
first argument and the handlers re-established.
Macro EXT:WITHOUT-GLOBAL-HANDLERS. The macro ( removes all global handlers by EXT:WITHOUT-GLOBAL-HANDLERS &BODY
body)(, executes EXT:SET-GLOBAL-HANDLER
NIL NIL)body (where unhandled conditions now
invoke the debugger), and then restores the handlers.
The prompt for replacement values (RESTARTs STORE-VALUE,
USE-VALUE et al) is terminated with CUSTOM:*PROMPT-FINISH* to indicate that
the value entered is treated as usual for the Lisp read-eval-print loop, i.e., it is
EVALuated.
No notes.
Table of Contents
The [ANSI CL standard] packages present in CLISP
MAKE-PACKAGEThe default value of the :USE argument is
(“COMMON-LISP”).
MAKE-PACKAGE accepts additional keyword arguments
:CASE-SENSITIVE and :CASE-INVERTED (but not :MODERN!)
DEFPACKAGEDEFPACKAGE accepts additional options :CASE-SENSITIVE,
:CASE-INVERTED, and :MODERN.
When the package being defined already exists, it is modified as follows (and in this order):
:CASE-SENSITIVE(SETF EXT:PACKAGE-CASE-SENSITIVE-P)
(with a warning):CASE-INVERTED(SETF EXT:PACKAGE-CASE-INVERTED-P)
(with a warning):MODERNif “COMMON-LISP” is being used, it is un-used and
“CS-COMMON-LISP” is used instead; also, “CS-COMMON-LISP” is used instead of “COMMON-LISP”
throughout the DEFPACKAGE form, e.g.,
(DEFPACKAGE"FOO" (:MODERNT) (:USE"COMMON-LISP" "EXT"))
is equivalent to
(DEFPACKAGE"FOO" (:CASE-SENSITIVET) (:CASE-INVERTEDT) (:USE"CS-COMMON-LISP" "EXT"))
:NICKNAMESRENAME-PACKAGE
:DOCUMENTATION(SETF
DOCUMENTATION):SHADOWSHADOW
:SHADOWING-IMPORT-FROMSHADOWING-IMPORT
:USEUSE-PACKAGE and UNUSE-PACKAGE
:IMPORT-FROMIMPORT
:INTERNINTERN (but not UNINTERN)
:EXPORTINTERN and EXPORT (but not
UNEXPORT):SIZEEXT:RE-EXPORTThe function ( re-EXT:RE-EXPORT FROM-PACK
TO-PACK)EXPORTs all external
SYMBOLs from FROM-PACK also from
TO-PACK, provided it already uses
FROM-PACK; and SIGNALs an ERROR otherwise.
EXT:PACKAGE-CASE-INVERTED-PReturns T if the argument is a
case-inverted package.
This function is SETFable, although it is probably not a good idea
to change the case-inverted status of an existing package.
EXT:PACKAGE-CASE-SENSITIVE-PReturns T if the argument is a :CASE-SENSITIVE PACKAGE.
This function is SETFable, although it is probably not a good idea
to change the case-sensitive status of an existing package.
Locking discussed in this section has nothing to do with
MT:MUTEX-LOCK.
Function EXT:PACKAGE-LOCK
. Packages can be “locked”.
When a package is locked, attempts to change its symbol table or
redefine functions which its symbols name result in a continuable ERROR
(continuing overrides locking for this operation).
When CUSTOM:*SUPPRESS-CHECK-REDEFINITION* is T (not a good idea!), the ERROR
is not SIGNALed for redefine operations.
Function (
returns the generalized boolean indicating whether the EXT:PACKAGE-LOCK package)package is locked.
A package (or a list thereof) can be locked using (.
CLISP locks its system packages (specified in the variable
SETF
(EXT:PACKAGE-LOCK package-or-list) T)CUSTOM:*SYSTEM-PACKAGE-LIST*).
Macro EXT:WITHOUT-PACKAGE-LOCK. If you want to evaluate some forms with certain packages unlocked,
you can use
EXT:WITHOUT-PACKAGE-LOCK
:
(EXT:WITHOUT-PACKAGE-LOCK (“COMMON-LISP” “EXT” “CLOS”)
(defun restart () ...))
or
(EXT:WITHOUT-PACKAGE-LOCK (“COMMON-LISP”) (trace read-line))
(
temporarily unlocks all packages in EXT:WITHOUT-PACKAGE-LOCK () ...)CUSTOM:*SYSTEM-PACKAGE-LIST*.
Variable CUSTOM:*SYSTEM-PACKAGE-LIST*. This variable specifies the default packages to be locked by EXT:SAVEINITMEM
and unlocked by EXT:WITHOUT-PACKAGE-LOCK as a list of package names.
You may add names to this list, e.g., a module will add its package,
but you should not remove CLISP internal packages from this list.
Discussion - see also the USENET posting by . This should prevent you from accidentally hosing yourself with
(DEFSTRUCT instance ...)
and allow enforcing modularity.
Note that you will also get the continuable ERROR when you try to
assign (with SETQ, PSETQ, etc.) a value to an internal special
variable living in a locked package and not accessible in your current
*PACKAGE*, but only in the interpreted code and during compilation.
There is no check for package locks in compiled code because of the
performance considerations.
The “COMMON-LISP-USER” package uses the “COMMON-LISP” and “EXT” packages.
The following additional packages exist:
Implementation-Defined Packages
EXPORTs all CLOS-specific symbols, including some
additional symbols.
EXPORTed symbols. It defines many system internals.
EXT:RE-EXPORTs
all the external symbols in all CLISP extensions, so a simple
(USE-PACKAGE "EXT") is enough to
make all the extensions available in the current package.
This package uses packages (in addition to “COMMON-LISP”):
“POSIX”, “SOCKET”, “GSTREAM”, “GRAY”,
“I18N”, “CUSTOM”.EXPORTs some character sets, for use with
EXT:MAKE-ENCODING and as :EXTERNAL-FORMAT argument.
:CASE-SENSITIVE versions of “COMMON-LISP” and “COMMON-LISP-USER”.
See Section 11.5, “Package Case-Sensitivity”.All pre-existing packages except “COMMON-LISP-USER” belong to the implementation, in the sense that the programs that do not follow [sec_11-1-2-1-2] (“Constraints on the ‘COMMON-LISP’ Package for Conforming Programs”) cause undefined behavior.
CLISP supports programs written with case sensitive symbols. For
example, with case sensitive symbols, the symbols cdr
(the function equivalent to REST) and the symbol CDR
(a user-defined type denoting a Call Data Record) are different and unrelated.
There are some incompatibilities between programs assuming case
sensitive symbols and programs assuming the [ANSI CL standard] case insensitive symbols.
For example, (eq 'KB 'Kb) evaluates to false in a case
sensitive world and to true in a case insensitive world. However, unlike some
commercial Common Lisp implementations, CLISP allows both kinds of programs to
coexist in the same process and interoperate with each other. Example:
OLD.lisp(IN-PACKAGE"OLD") (DEFUNFOO () ...)
modern.lisp
(in-package "NEW")
(defun bar () (old:foo))
(symbol-name 'bar) ; ⇒ "bar"
This is achieved through specification of the symbol case policy at the package level. A modern package is one that is declared to be both case-sensitive and case-inverted and which use the symbols from the “CS-COMMON-LISP” package.
A case-sensitive package
is one whose DEFPACKAGE declaration (or MAKE-PACKAGE
creation form) has the option (.
In a case-sensitive package, the reader does not uppercase the
symbol name before calling :CASE-SENSITIVE T)INTERN. Similarly, the printer, when
printing the SYMBOL-NAME part of a SYMBOL (i.e. the part after
the package markers), behaves as if the readtable's case were set
to :PRESERVE.
See also Section 11.1.5, “Function EXT:PACKAGE-CASE-SENSITIVE-P”.
A case-inverted package
is one whose DEFPACKAGE declaration (or MAKE-PACKAGE
creation form) has the option (.
In the context of a case-inverted package, symbol names are
case-inverted: upper case characters are mapped to lower case, lower
case characters are mapped to upper case, and other characters are left
untouched. Every symbol thus conceptually has two symbol names: an
old-world symbol name and a modern-world symbol name, which is the
case-inverted old-world name. The first symbol name is returned by the
function :CASE-INVERTED T)SYMBOL-NAME, the modern one by the
function cs-cl:symbol-name. The internal
functions for creating or looking up symbols in a package, which
traditionally took a string argument, now conceptually take two string
arguments: old-style-string and inverted-string. Actually, a function
like INTERN takes the old-style-string as argument and computes the
inverted-string from it; whereas the
function cs-cl:intern takes the inverted-string as
argument and computes the old-style-string from it.
See also Section 11.1.4, “Function EXT:PACKAGE-CASE-INVERTED-P”.
For a few built-in functions, a variant for the case-inverted world is defined in the “CS-COMMON-LISP” package, which has the nickname “CS-CL”:
cs-cl:symbol-namecs-cl:interncs-cl:find-symbolcs-cl:symbol-name.cs-cl:shadowcs-cl:find-all-symbolscs-cl:string=cs-cl:string/=cs-cl:string<cs-cl:string>cs-cl:string<=cs-cl:string>=cs-cl:string-trimcs-cl:string-left-trimcs-cl:string-right-trimSYMBOL to a STRING and therefore
exist in a variant that uses cs-cl:symbol-name
instead of SYMBOL-NAME.cs-cl:make-packagePACKAGE.
A package “CS-COMMON-LISP-USER” is provided for the user to modify and work in. It plays the same role as “COMMON-LISP-USER”, but for the case-sensitive world.
The handling of package names is unchanged. Package names are
still usually uppercase. The package names are also subject to
(.READTABLE-CASE *READTABLE*)
Note that gensyms and keywords are still treated traditionally: even in a case-sensitive package,
(STRING='#:FooBar '#:foobar) ⇒(TEQ':KeyWord ':keyword) ⇒T
We believe this has a limited negative impact for the moment, but can be changed some time in the future.
The following practices will pose no problems when migrating to a modern case-sensitive world:
(STRING= (SYMBOL-NAME x) (SYMBOL-NAME y)).
The following practices will not work in a case-sensitive world or can give problems:
SYMBOL-NAME return values with EQ.
(SYMBOL-NAME x) with
(cs-cl:symbol-name y).CLISP supports a command-line option -modern that
sets the *PACKAGE* initially to the “CS-COMMON-LISP-USER” package, and
*PRINT-CASE* to :DOWNCASE.
For packages to be located in the “modern”
(case-sensitive) world, you need to augment their DEFPACKAGE
declaration by adding the option (,
see Section 11.1.2, “Macro :MODERN T)DEFPACKAGE”.
Table of Contents
The type NUMBER is the disjoint union of the types
REAL and COMPLEX (exhaustive
partition)
The type REAL is the disjoint union of the types
RATIONAL and FLOAT.
The type RATIONAL is the disjoint union of the types
INTEGER and RATIO.
The type INTEGER is the disjoint union of the types
FIXNUM and BIGNUM.
The type FLOAT is the disjoint union of the types
SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT and
LONG-FLOAT.
Function EXT:! ( returns the
factorial of EXT:! n)n, n being a nonnegative INTEGER.
Function EXT:EXQUO. ( returns
the integer quotient EXT:EXQUO x y)x/y of two integers
x,y, and SIGNALs an ERROR when the quotient is not
integer. (This is more efficient than /.)
Function EXT:XGCD. (
returns the values EXT:XGCD x1 ... xn)l, k1, ..., kn, where l is the
greatest common divisor of the integers x1, ..., xn, and
k1, ..., kn are the integer coefficients such that
l= (GCDx1...xn) = (+ (*k1x1) ... (*knxn))
Function EXT:MOD-EXPT. (
is equivalent to EXT:MOD-EXPT k l m)(
except it is more efficient for very large arguments.MOD (EXPT k l) m)
DECODE-FLOATFLOAT-RADIX always returns 2.
( coerces
FLOAT-DIGITS number digits)number (a REAL) to a floating point number with at least
digits mantissa digits. The following always evaluates to T:
(>=(FLOAT-DIGITS(FLOAT-DIGITSnumberdigits))digits)
Byte specifiers are objects of built-in type BYTE,
not INTEGERs.
Function EXPT. (
is not very precise if EXPT base exponent)exponent has a large
absolute value.
Function LOG. ( LOG number base)SIGNALs an ERROR if
.base = 1
Constant PI. The value of PI is a LONG-FLOAT with the precision given
by (. When this precision is changed, the value of EXT:LONG-FLOAT-DIGITS)PI is
automatically recomputed. Therefore PI is not a constant variable.
Function UPGRADED-COMPLEX-PART-TYPE. When the argument is not a recognizable subtype or REAL,
UPGRADED-COMPLEX-PART-TYPE SIGNALs an ERROR, otherwise it
returns its argument (even though a COMPLEX number in CLISP can
always have REALPART and IMAGPART of any type) because it allows
the most precise type inference.
Variable CUSTOM:*DEFAULT-FLOAT-FORMAT*. When rational numbers are to be converted to floats (due to
FLOAT, COERCE, SQRT or a transcendental function), the result
type is given by the variable CUSTOM:*DEFAULT-FLOAT-FORMAT*.
See also *READ-DEFAULT-FLOAT-FORMAT*.
Macro EXT:WITHOUT-FLOATING-POINT-UNDERFLOW. The macro ( executes the
EXT:WITHOUT-FLOATING-POINT-UNDERFLOW {form}*)forms, with errors of type FLOATING-POINT-UNDERFLOW inhibited.
Floating point operations will silently return zero instead of
SIGNALing an ERROR of type FLOATING-POINT-UNDERFLOW.
Condition FLOATING-POINT-INVALID-OPERATION. This CONDITION is never SIGNALed by CLISP.
Condition FLOATING-POINT-INEXACT. This CONDITION is never SIGNALed by CLISP.
Table 12.2. Fixnum limits
| CPU type | 32-bit CPU | 64-bit CPU |
|---|---|---|
MOST-POSITIVE-FIXNUM | 224-1 = 16777215 | 248-1 = 281474976710655 |
MOST-NEGATIVE-FIXNUM | -224 = -16777216 | -248 = -281474976710656 |
BIGNUMs are limited in size. Their maximum size is
32*(216-2)=2097088 bits.
The largest representable BIGNUM is therefore
22097088-1.
Together with PI, the other LONG-FLOAT constants
are recomputed whenever ( is EXT:LONG-FLOAT-DIGITS)SETFed.
They are not constant variables.
Since the exponent of a
LONG-FLOAT is a signed 32-bits
integer, MOST-POSITIVE-LONG-FLOAT is about
2231,
which is much larger that the largest
representable BIGNUM, which is less than
2221.
This, obviously, means that ROUND, TRUNCATE, FLOOR and CEILING
SIGNALs an ERROR on large LONG-FLOATs.
Less obviously, this means that ( also fails.FORMAT NIL "~E"
MOST-POSITIVE-LONG-FLOAT)
When a mathematical function may return an exact (RATIONAL) or
inexact (FLOAT) result, it always returns the exact result.
There are four floating point types: SHORT-FLOAT,
SINGLE-FLOAT, DOUBLE-FLOAT and LONG-FLOAT:
| type | sign | mantissa | exponent | comment |
|---|---|---|---|---|
SHORT-FLOAT | 1 bit | 16+1 bits | 8 bits | immediate |
SINGLE-FLOAT | 1 bit | 23+1 bits | 8 bits | IEEE 754 |
DOUBLE-FLOAT | 1 bit | 52+1 bits | 11 bits | IEEE 754 |
LONG-FLOAT | 1 bit | >=64 bits | 32 bits | variable length |
The single and double float formats are those of the IEEE 754
“Standard for Binary Floating-Point Arithmetic”,
except that CLISP does not support features like
±0, ±inf,
NaN, gradual underflow, etc.
Common Lisp does not make use of these features, so, to reduce portability
problems, CLISP by design returns the same floating point results on
all platforms (CLISP has a floating-point emulation built in for
platforms that do not support IEEE 754). Note that
NaN
in your program, your program is broken, so you will spend time
determining where the NaN came from.
It is better to SIGNAL an ERROR in this case.LONG-FLOATs of
variable precision - it does not
need unnormalized floats.
This is why *FEATURES* does not contain the
:IEEE-FLOATING-POINT keyword.
Arbitrary Precision Floats. LONG-FLOATs have variable mantissa length, which is a
multiple of 16 (or 32, depending on the word size of the processor).
The default length used when LONG-FLOATs are READ is given by the
place (. It can be set by EXT:LONG-FLOAT-DIGITS)(,
where SETF (EXT:LONG-FLOAT-DIGITS) n)n is a positive INTEGER. E.g., ( sets the default precision of SETF (EXT:LONG-FLOAT-DIGITS)
3322)LONG-FLOATs to about
1000 decimal digits.
The floating point contagion is controlled by the variable
CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*. When it is non-NIL, contagion is done as per the
[ANSI CL standard]: SHORT-FLOAT → SINGLE-FLOAT →
DOUBLE-FLOAT → LONG-FLOAT.
1.5 is actually 1.5±0.05.
Consider adding 1.5 and 1.75.
[ANSI CL standard] requires that (+ 1.5 1.75)
return 3.25, while traditional CLISP
would return 3.3.
The implied random variables are: 3.25±0.005
and 3.3±0.05.
Note that the traditional CLISP way does
lie about the mean: the mean is 3.25 and
nothing else, while the standard way
could be lying about the deviation
(accuracy): if the implied accuracy of 1.5 (i.e., 0.05)
is its actual accuracy, then the accuracy of the result cannot be
smaller that that. Therefore, since Common Lisp has no way of knowing the
actual accuracy, [ANSI CL standard] (and all the other standard engineering
programming languages, like C, Fortran
etc) decided that keeping the accuracy correct is the business of the
programmer, while the language should preserve what it can - the precision.
E(x2) -
E(x)2 can be negative!)
The user should not mix floats of different precision (that's what
CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION* is for), but one should not be penalized for this too
harshly.When CUSTOM:*FLOATING-POINT-CONTAGION-ANSI* is NIL, the traditional CLISP method is used,
namely the result of an arithmetic operation whose arguments are of
different float types is rounded to the float format of the shortest
(least precise) of the arguments: RATIONAL →
LONG-FLOAT → DOUBLE-FLOAT → SINGLE-FLOAT
→ SHORT-FLOAT (in contrast to
[sec_12-1-4-4]!)
{1.0 ± 1e-8} + {1.0 ± 1e-16} = {2.0 ±
1e-8}. So, if we add 1.0s0 and
1.0d0, we should get 2.0s0.
(- (+ 1.7 PI) PI)
should not return 1.700000726342836417234L0,
it should return 1.7f0 (or
1.700001f0 if there were rounding errors).
SHORT-FLOATs,
a LONG-FLOAT (like PI) happens to be used, the long precision
should not propagate throughout all the intermediate values.
Otherwise, the long result would look precise, but its accuracy is
only that of a SHORT-FLOAT; furthermore much computation time
would be lost by calculating with LONG-FLOATs when only
SHORT-FLOATs would be needed.If the variable CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION* is non-NIL, a WARNING is emitted for
every coercion involving different floating-point types.
As explained above, float precision contagion is not a good idea.
You can avoid the contagion by doing all your computations with the
same floating-point type (and using FLOAT to convert all constants,
e.g., PI, to your preferred type).
This variable helps you eliminate all occurrences of float
precision contagion: set it to T to have CLISP SIGNAL a
WARNING on float precision contagion; set it to ERROR to have
CLISP SIGNAL an ERROR on float precision contagion, so that you
can look at the stack backtrace.
The contagion between floating point and rational numbers is controlled
by the variable CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*. When it is non-NIL, contagion is done as per
the [ANSI CL standard]: RATIONAL → FLOAT.
When CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI* is NIL, the traditional CLISP method is used,
namely if the result is mathematically an exact rational number, this
rational number is returned (in contrast to
[sec_12-1-4-1]!)
CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI* has an effect only in those few cases when the mathematical
result is exact although one of the arguments is a floating-point number,
such as (, * 0 1.618)(,
/ 0 1.618)(, ATAN 0 1.0)(,
EXPT 2.0 0)(.PHASE 2.718)
If the variable CUSTOM:*WARN-ON-FLOATING-POINT-RATIONAL-CONTAGION* is non-NIL, a WARNING is emitted for
every avoidable coercion from a rational number to a floating-point number.
You can avoid such coercions by calling FLOAT to convert the particular
rational numbers to your preferred floating-point type.
This variable helps you eliminate all occurrences of avoidable
coercions to a floating-point number when a rational number result
would be possible: set it to T to have CLISP SIGNAL a WARNING
in such situations; set it to ERROR to have CLISP SIGNAL an
ERROR in such situations, so that you can look at the stack
backtrace.
CUSTOM:*PHASE-ANSI*A similar variable, CUSTOM:*PHASE-ANSI*, controls the return
value of PHASE when the argument is an exact nonnegative REAL.
Namely, if CUSTOM:*PHASE-ANSI* is non-NIL, it returns a floating-point zero;
if CUSTOM:*PHASE-ANSI* is NIL, it returns an exact zero. Example:
(PHASE 2/3)
Complex numbers can have a real part and an imaginary part of
different types. For example, ( evaluates to
the number SQRT -9.0),
which has a real part of exactly #C(0 3.0)0,
not only 0.0
(which would mean “approximately 0”).
The type specifier for this is (, and COMPLEX
INTEGER SINGLE-FLOAT)( in general.COMPLEX
type-of-real-part
type-of-imaginary-part)
The type specifier ( is equivalent to COMPLEX
type)(.COMPLEX
type type)
Complex numbers can have a real part and an imaginary part of
different types. If the imaginary part is EQL to 0,
the number is automatically converted to a real number.
This has the advantage that
( - instead of
evaluating to LET ((x (SQRT -9.0))) (* x x)),
with #C(-9.0 0.0)x = -
evaluates to #C(0.0 3.0) =
#C(-9.0 0)-9.0,
with x = .#C(0 3.0)
To ease reproducibility, the variable *RANDOM-STATE* is
initialized to the same value on each invocation, so that
$clisp -norc-x'(RANDOM1s0)'
will always print the same number.
If you want a new random state on each invocation, you can arrange for that by using init function:
$clisp -norc-x'(EXT:SAVEINITMEM"foo" :init-function (LAMBDA() (SETQ*RANDOM-STATE*(MAKE-RANDOM-STATET))))'$clisp -norc-Mfoo.mem-x'(RANDOM1s0)'
or by placing ( into your RC file.SETQ *RANDOM-STATE*
(MAKE-RANDOM-STATE T))
Table of Contents
CHAR-CODECHAR-CODE takes values from 0 (inclusive) to
CHAR-CODE-LIMIT (exclusive), i.e., the implementation
supports exactly CHAR-CODE-LIMIT characters.
Table 13.1. Number of characters
| binaries built | without UNICODE support | with UNICODE support |
|---|---|---|
CHAR-CODE-LIMIT | 28 = 256 | 17 * 216 = 1114112 |
BASE-CHARThe types EXT:STRING-CHAR and
BASE-CHAR are equivalent to CHARACTER.
EXT:STRING-CHAR used to be available as
STRING-CHAR prior to removal from [ANSI CL standard] by
CHARACTER-PROPOSAL:2.
EXT:CHAR-WIDTH( returns the number of screen
columns occupied by EXT:CHAR-WIDTH char)char. The value is
See also function EXT:STRING-WIDTH.
The characters are ordered according to a superset of the ASCII character set.
More precisely, CLISP uses the ISO Latin-1 (ISO 8859-1) character set:
| #x0 | #x1 | #x2 | #x3 | #x4 | #x5 | #x6 | #x7 | #x8 | #x9 | #xA | #xB | #xC | #xD | #xE | #xF | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| #x00 | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** |
| #x10 | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** |
| #x20 | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / | |
| #x30 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
| #x40 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
| #x50 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
| #x60 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
| #x70 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ | |
| #x80 | ||||||||||||||||
| #x90 | ||||||||||||||||
| #xA0 | ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | ¬ | | ® | ¯ | |
| #xB0 | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | º | » | ¼ | ½ | ¾ | ¿ |
| #xC0 | À | Á | Â | Ã | Ä | Å | Æ | Ç | È | É | Ê | Ë | Ì | Í | Î | Ï |
| #xD0 | Ð | Ñ | Ò | Ó | Ô | Õ | Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß |
| #xE0 | à | á | â | ã | ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï |
| #xF0 | ð | ñ | ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
Here ** are control characters, not graphic characters. (The characters left blank here cannot be represented in this character set).
Table 13.3. Semi-standard characters
| character | code |
|---|---|
| #\Backspace | #x08 |
| #\Tab | #x09 |
| #\Linefeed | #x0A |
| #\Page | #x0C |
| #\Return | #x0D |
#\Newline is the line terminator.
Table 13.5. Additional syntax for characters with code from #x00 to #x1F:
| character | code |
|---|---|
| #\^@ | #x00 |
| #\^A … #\^Z | #x01 … #x1A |
| #\^[ | #x1B |
| #\^\ | #x1C |
| #\^] | #x1D |
| #\^^ | #x1E |
| #\^_ | #x1F |
See also Section 2.6.1, “Sharpsign Backslash ”.
The only defined character script is the type CHARACTER
itself.
Characters have no implementation-defined or [CLtL1] font and bit attributes. All characters are simple characters.
For backward compatibility, there is a class SYS::INPUT-CHARACTER
representing either a character with font and bits, or a keystroke.
The following functions work with objects of types CHARACTER
and SYS::INPUT-CHARACTER.
Note that EQL or EQUAL are equivalent to EQ on objects of type
SYS::INPUT-CHARACTER.
EXT:CHAR-FONT-LIMIT = 16EXT:CHAR-BITS-LIMIT = 16Character bits:
| key | value |
|---|---|
:CONTROL | EXT:CHAR-CONTROL-BIT |
:META | EXT:CHAR-META-BIT |
:SUPER | EXT:CHAR-SUPER-BIT |
:HYPER | EXT:CHAR-HYPER-BIT |
(EXT:CHAR-FONT
object)CHARACTER or SYS::INPUT-CHARACTER.
(EXT:CHAR-BITS
object)CHARACTER or SYS::INPUT-CHARACTER.
(EXT:MAKE-CHAR
char [bits
[font]])SYS::INPUT-CHARACTER, or NIL if such a
character cannot be created.(EXT:CHAR-BIT
object name)T if the named bit is set in object,
else NIL.(EXT:SET-CHAR-BIT
object name new-value)SYS::INPUT-CHARACTER with the named bit set or
unset, depending on the BOOLEAN new-value.
SYS::INPUT-CHARACTER is not a subtype of
CHARACTER.
SYS::INPUT-CHARACTER type only to
mention special keys and Control/Alternate/Shift key status on return from
(READ-CHAR EXT:*KEYBOARD-INPUT*).The graphic characters are those UNICODE characters which are defined by the UNICODE standard, excluding the ranges U0000 … U001F and U007F … U009F.
The alphabetic characters are those UNICODE characters which are defined as letters by the UNICODE standard, e.g., the ASCII characters
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
and the international alphabetic characters from the character set:
ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜßáíóúñѪºãõØøÀÃÕ
etc.
EXT:CHAR-INVERTCASE( returns the corresponding
character in the other case for EXT:CHAR-INVERTCASE char)CHAR, i.e., CHAR-UPCASE for a
lowercase character and CHAR-DOWNCASE for an uppercase character; for
a character that does not have a case attribute, the argument is returned.
See also EXT:STRING-INVERTCASE and EXT:NSTRING-INVERTCASE.
The characters with case are those UNICODE characters c, for
which the upper case mapping uc and the lower case mapping lc
have the following properties:
uc and lc are differentc is one of uc and lcuc and of lc
is ucuc and of lc
is lcThe titlecase property of UNICODE characters has no equivalent in Common Lisp.
The numeric characters are those UNICODE characters which are defined as digits by the UNICODE standard.
The characters are ordered according to their UNICODE code.
The functions CHAR-EQUAL CHAR-NOT-EQUAL, CHAR-LESSP,
CHAR-GREATERP, CHAR-NOT-GREATERP, CHAR-NOT-LESSP ignore bits and
font attributes of their arguments.
Newlines are written according to the stream's EXT:ENCODING, see the
function STREAM-EXTERNAL-FORMAT and the description of EXT:ENCODINGs,
in particular, line terminators.
The default behavior is as follows:
When reading from a file, CR/LF is converted to #\Newline
(the usual convention on DOS), and CR not followed by LF is
converted to #\Newline as well (the usual conversion on MacOS, also used
by some programs on Win32).
If you do not want this, i.e., if you really want to distinguish
LF, CR and CR/LF, you have to resort to
binary input (function READ-BYTE).
Justification. Unicode Newline Guidelines say: “Even if you know which characters represents NLF on your particular platform, on input and in interpretation, treat CR, LF, CRLF, and NEL the same. Only on output do you need to distinguish between them.”
Rationale. In CLISP, #\Newline is identical to #\Linefeed
(which is specifically permitted by the [ANSI CL standard] in
[sec_13-1-7] “Character Names”).
Consider a file containing exactly this string:
(
Suppose we open it with CONCATENATE 'STRING "foo" (STRING #\Linefeed)
"bar" (STRING #\Return) (STRING #\Linefeed))(.
What should OPEN "foo" :EXTERNAL-FORMAT :DOS)READ-LINE return?
Right now, it returns "foo"
(the second READ-LINE returns "bar"
and reaches end-of-stream).
If our i/o were “faithful”, READ-LINE would have
returned the string (, i.e., a string with an embedded #\Newline
between "foo"
and "bar" (because a single #\Linefeed is not a
#\Newline in the specified CONCATENATE 'STRING "foo" (STRING
#\Linefeed) "bar"):EXTERNAL-FORMAT, it will not make READ-LINE return,
but it is a CLISP #\Newline!) Even though the specification for
READ-LINE does not explicitly forbids newlines inside the returned
string, such behavior would be quite surprising, to say the least.
Moreover, this line (with an embedded #\Newline) would be written as two
lines (when writing to a STREAM with :EXTERNAL-FORMAT of :DOS), because
the embedded #\Newline would be written as CR+LF.
The integer returned by CHAR-INT is the same as the character's
code (CHAR-CODE).
The characters that are not graphic chars and the space character have names:
Table 13.6. Additional characters (Platform Dependent: Win32 platform only.)
| code | char | |
|---|---|---|
( | #\Null | |
( | #\Bell | |
( | #\Backspace | |
( | #\Tab | |
( | #\Newline | #\Linefeed |
( | #\Code11 | |
( | #\Page | |
( | #\Return | |
( | #\Code26 | |
( | #\Escape | #\Esc |
( | #\Space | |
( | #\Rubout |
Table 13.7. Additional characters (Platform Dependent: UNIX platform only.)
| code | char | ||
|---|---|---|---|
( | #\Null | #\Nul | |
( | #\Soh | ||
( | #\Stx | ||
( | #\Etx | ||
( | #\Eot | ||
( | #\Enq | ||
( | #\Ack | ||
( | #\Bell | #\Bel | |
( | #\Backspace | #\Bs | |
( | #\Tab | #\Ht | |
( | #\Newline | #\Nl | #\Linefeed |
( | #\Vt | ||
( | #\Page | #\Np | |
( | #\Return | #\Cr | |
( | #\So | ||
( | #\Si | ||
( | #\Dle | ||
( | #\Dc1 | ||
( | #\Dc2 | ||
( | #\Dc3 | ||
( | #\Dc4 | ||
( | #\Nak | ||
( | #\Syn | ||
( | #\Etb | ||
( | #\Can | ||
( | #\Em | ||
( | #\Sub | ||
( | #\Escape | #\Esc | |
( | #\Fs | ||
( | #\Gs | ||
( | #\Rs | ||
( | #\Us | ||
( | #\Space | #\Sp | |
( | #\Rubout | #\Delete | #\Del |
Table of Contents
Function EXT:MAPCAP. The function EXT:MAPCAP is like MAPCAN, except that it
concatenates the resulting lists with APPEND instead of NCONC:
(EXT:MAPCAPfunctionx1...xn) ≡ (APPLY#'APPEND(MAPCARfunctionx1...xn))
(Actually a bit more efficient that this would have been.)
Function EXT:MAPLAP. The function EXT:MAPLAP is like MAPCON, except that it
concatenates the resulting lists with APPEND instead of NCONC:
(EXT:MAPLAPfunctionx1...xn) ≡ (APPLY#'APPEND(MAPLISTfunctionx1...xn))
(Actually a bit more efficient that this would have been.)
Table of Contents
Function MAKE-ARRAY. MAKE-ARRAY can return specialized arrays for the ARRAY-ELEMENT-TYPEs
(,
UNSIGNED-BYTE 2)(,
UNSIGNED-BYTE 4)(, UNSIGNED-BYTE 8)(, UNSIGNED-BYTE 16)(, and, of course, the required
specializations UNSIGNED-BYTE 32)NIL, BIT and CHARACTER.
Function ADJUST-ARRAY for displaced arrays. An array to which another array is displaced should not be shrunk
(using ADJUST-ARRAY) in such a way that the other array points into
void space. This cannot be checked at the time ADJUST-ARRAY is
called!
Table 15.1. Array limits
| CPU type | 32-bit CPU | 64-bit CPU |
|---|---|---|
ARRAY-RANK-LIMIT | 212 = 4096 | |
ARRAY-DIMENSION-LIMIT | 224-1 = 16777215 | 232-1 = 4294967295 |
ARRAY-TOTAL-SIZE-LIMIT | 224-1 = 16777215 | 232-1 = 4294967295 |
Table of Contents
String comparison (STRING< and friends) is based on the
function CHAR<= (see Section 13.9, “Ordering of Characters ”).
Therefore diphthongs do not obey the usual national rules. Example:
o < oe < z < ö.
EXT:STRING-WIDTH( returns the number of screen columns occupied by
EXT:STRING-WIDTH string &KEY start
end)string. This is computed as the sum of all EXT:CHAR-WIDTHs of all
of the string's characters:
(REDUCE#'+string:KEY#'EXT:CHAR-WIDTH)
EXT:STRING-INVERTCASE
and EXT:NSTRING-INVERTCASE(
and EXT:STRING-INVERTCASE string &KEY start end)(
are similar to EXT:NSTRING-INVERTCASE string &KEY start end)STRING-UPCASE et al: they use EXT:CHAR-INVERTCASE to
invert the case of each characters in the argument string region.
Table of Contents
Function NREVERSE. The result of NREVERSE is always EQ to the argument.
NREVERSE on a VECTOR swaps pairs of elements.
NREVERSE on a LIST swaps the first and the last
element and reverses the list chaining between them.
Function NRECONC. The result of NRECONC is EQ to the first argument unless it is
NIL, in which case the result is EQ to the second argument.
REMOVE, REMOVE-IF, REMOVE-IF-NOT, REMOVE-DUPLICATES return
their argument unchanged, if no element has to be removed.
DELETE, DELETE-IF, DELETE-IF-NOT, DELETE-DUPLICATES
destructively modify their argument: If the argument is a LIST,
the CDR parts are modified. If the argument is a VECTOR with
fill pointer, the fill pointer is lowered and the remaining elements are
compacted below the new fill pointer.
Variable CUSTOM:*SEQUENCE-COUNT-ANSI*. Contrary to the [ANSI CL standard] issue RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER,
negative :COUNT keyword arguments are not allowed unless you set
CUSTOM:*SEQUENCE-COUNT-ANSI* to a non-NIL value, in which case “using a
negative integer value is functionally equivalent to using a value of
zero”, as per the [ANSI CL standard] issue.
SORT & STABLE-SORTSORT and STABLE-SORT accept two additional keyword arguments
:START and :END:
(SORTsequencepredicate&KEY:KEY:START:END) (STABLE-SORTsequencepredicate&KEY:KEY:START:END)
SORT and STABLE-SORT are identical.
They implement the mergesort algorithm.
Worst case complexity: O(n*log(n)) comparisons,
where n is the LENGTH of the subsequence bounded
by the :START and :END arguments.
Table of Contents
If you “visibly modify” a key, consequences are unpredictable:
(LET((hash-table(MAKE-HASH-TABLE:test 'EQUALP))) (SETF(GETHASHhash-tablehash-table)T) (GETHASHhash-tablehash-table)) ⇒; ⇒NILNIL
because ( modifies SETF GETHASH)hash-table, the very next
GETHASH does not find it in itself.
MAKE-HASH-TABLEMAKE-HASH-TABLE accepts two additional keyword arguments
:INITIAL-CONTENTS and :WEAK:
(MAKE-HASH-TABLE&KEY:TEST :INITIAL-CONTENTS :SIZE :REHASH-SIZE :REHASH-THRESHOLD :WARN-IF-NEEDS-REHASH-AFTER-GC :WEAK)
The :TEST argument can be, other than one of the symbols EQ,
EQL, EQUAL, EQUALP, one of the symbols EXT:FASTHASH-EQ and
EXT:STABLEHASH-EQ. Both of these tests use EQ as the comparison
function; they differ in their performance characteristics.
EXT:FASTHASH-EQEXT:STABLEHASH-EQSYMBOL,
EXT:STANDARD-STABLEHASH (subclass of STANDARD-OBJECT) and
EXT:STRUCTURE-STABLEHASH (subclass of STRUCTURE-OBJECT) are
stable across GCs.
This test can thus avoid the scalability problems if all keys,
other than immediate objects, are SYMBOL, EXT:STANDARD-STABLEHASH or
EXT:STRUCTURE-STABLEHASH instances.
One can recommend to use EXT:FASTHASH-EQ for short-lived hash tables.
For tables with a longer lifespan which can be big or accessed
frequently, it is recommended to use EXT:STABLEHASH-EQ, and to modify the
objects that are used as its keys to become instances of
EXT:STANDARD-STABLEHASH or EXT:STRUCTURE-STABLEHASH.
When the symbol EQ or the function #'eq is
used as a :TEST argument, the value of the variable
CUSTOM:*EQ-HASHFUNCTION*
is used instead.
This value must be one of EXT:FASTHASH-EQ, EXT:STABLEHASH-EQ.
Similarly, the :TEST argument can also be one
of the symbols EXT:FASTHASH-EQL,
EXT:STABLEHASH-EQL,
EXT:FASTHASH-EQUAL,
EXT:STABLEHASH-EQUAL.
The same remarks apply as for EXT:FASTHASH-EQ and EXT:STABLEHASH-EQ.
When the symbol EQL or the function #'eql is used
as a :TEST argument, the value of the variable
CUSTOM:*EQL-HASHFUNCTION*
is used
instead; this value must be one of EXT:FASTHASH-EQL,
EXT:STABLEHASH-EQL.
Similarly, when the symbol EQUAL or the function #'equal
is used as a :TEST argument, the value of the variable
CUSTOM:*EQUAL-HASHFUNCTION*
is used
instead; this value must be one of EXT:FASTHASH-EQUAL,
EXT:STABLEHASH-EQUAL.
The :WARN-IF-NEEDS-REHASH-AFTER-GC argument,
if true, causes a WARNING to be SIGNALed when an object is stored
into the table which will force table reorganizations at the first
access of the table after each garbage-collection.
This keyword argument can be used to check whether EXT:STABLEHASH-EQ
should be preferred over EXT:FASTHASH-EQ for a particular table.
Use HASH-TABLE-WARN-IF-NEEDS-REHASH-AFTER-GC
to check and SETF this parameter after the table has been created.
The :INITIAL-CONTENTS argument is an
association list that is used to initialize the new hash table.
The :REHASH-THRESHOLD argument is ignored.
The :WEAK argument can take the following values:
NIL (default) |
:KEY |
:VALUE |
:KEY-AND-VALUE |
:KEY-OR-VALUE |
and specifies whether the HASH-TABLE is weak:
if the key, value, either or both are not accessible for the garbage-collection
purposes, i.e., if they are only accessible via weak HASH-TABLEs
and EXT:WEAK-POINTERs, it is garbage-collected and removed from the weak
HASH-TABLE.
The SETFable predicate EXT:HASH-TABLE-WEAK-P
checks whether the HASH-TABLE is weak.
Note that the only test that makes sense for weak hash tables are
EQ and its variants EXT:FASTHASH-EQ and EXT:STABLEHASH-EQ.
Just like all other weak objects, weak
HASH-TABLEs cannot be printed readably.
See also Section 31.7.9, “Weak Hash Tables”.
HASH-TABLEs and garbage-collectionWhen a hash table contains keys to be compared by identity - such
as NUMBERs in HASH-TABLEs with the HASH-TABLE-TEST EQ;
or CONSes in tables which test with EQ or EQL;
or VECTORs in tables which test with EQ, EQL or EQUAL;
or STANDARD-OBJECT or STRUCTURE-OBJECT instances in tables which
test with EQ, EQL, EQUAL or EQUALP;
- the hash code will in general depend on the object's address in
memory. Therefore it will in general be invalidated after a garbage-collection,
and the hash table's internal structure must be recomputed at the next
table access.
While :WARN-IF-NEEDS-REHASH-AFTER-GC can help
checking the efficiency of a particular HASH-TABLE, the variable
CUSTOM:*WARN-ON-HASHTABLE-NEEDING-REHASH-AFTER-GC*
achieves the same effect for all HASH-TABLEs in the system at once:
when CUSTOM:*WARN-ON-HASHTABLE-NEEDING-REHASH-AFTER-GC* is true and a
HASH-TABLE needs to be rehashed after a garbage-collection, a warning is
issued that shows the inefficient HASH-TABLE.
What can be done to avoid the inefficiencies detected by these warnings?
STABLEHASH variant of the hash
test.STANDARD-OBJECT or
STRUCTURE-OBJECT instances, you can solve the problem by making
the key object classes inherit from EXT:STANDARD-STABLEHASH or
EXT:STRUCTURE-STABLEHASH, respectively.EXT:DEFINE-HASH-TABLE-TESTYou can define a new hash table test using the macro
EXT:DEFINE-HASH-TABLE-TEST: (, after
which EXT:DEFINE-HASH-TABLE-TEST test-name test-function hash-function)name can be passed as the :TEST argument to MAKE-HASH-TABLE.
E.g.:
(EXT:DEFINE-HASH-TABLE-TESTstringSTRING=SXHASH) ⇒STRING(MAKE-HASH-TABLE:test 'string) ⇒#S(HASH-TABLE :TEST (#<SYSTEM-FUNCTION STRING=> . #<SYSTEM-FUNCTION SXHASH>))
(which is not too useful because it is equivalent to an EQUAL
HASH-TABLE but less efficient).
The fundamental requirement is that the test-function and hash-function are
consistent:
(FUNCALLtest-functionxy) ⇒ (=(FUNCALLhash-functionx) (FUNCALLhash-functiony))
This means that the following definition:
(EXT:DEFINE-HASH-TABLE-TESTnumber=SXHASH) ; broken!
is not correct because
(=1 1d0) ⇒; same object! (T=(SXHASH1) (SXHASH1d0)) ⇒; different buckets!NIL
The correct way is, e.g.:
(EXT:DEFINE-HASH-TABLE-TESTnumber=(LAMBDA(x) (SXHASH(COERCEx 'SHORT-FLOAT))))
Note that COERCEing to a SHORT-FLOAT does not cons up
fresh objects while COERCEing to a DOUBLE-FLOAT does.
HASH-TABLE-TESTFunction HASH-TABLE-TEST returns either one of
EXT:FASTHASH-EQ | EXT:FASTHASH-EQUAL |
EXT:STABLEHASH-EQ | EXT:STABLEHASH-EQUAL |
EXT:FASTHASH-EQL | EQUALP |
EXT:STABLEHASH-EQL |
(but not EQ, EQL nor EQUAL anymore), or, for HASH-TABLEs
created with a user-defined HASH-TABLE-TEST (see macro EXT:DEFINE-HASH-TABLE-TEST),
a CONS cell (test-function . hash-function).
EXT:DOHASHFor iteration through a HASH-TABLE, a macro EXT:DOHASH,
similar to DOLIST, can be used instead of MAPHASH:
(EXT:DOHASH(key-varvalue-varhash-table-form[resultform]) {declaration}* {tag|form}*)
EXT:DOHASH forms are iteration forms.
Table of Contents
For most operations, pathnames denoting files and pathnames denoting directories cannot be used interchangeably.
#P"foo/bar" denotes
the file #P"bar" in the directory #P"foo",
while #P"foo/bar/" denotes the subdirectory
#P"bar" of the directory #P"foo".
#P"foo\\bar"
denotes the file #P"bar" in the directory #P"foo",
while #P"foo\\bar\\" denotes the subdirectory
#P"bar" of the directory #P"foo".
CUSTOM:*DEVICE-PREFIX*
controls translation between Cygwin pathnames
(e.g., #P"/cygdrive/c/gnu/clisp/") and native
Win32 pathnames (e.g., #P"C:\\gnu\\clisp\\")
When it is set to NIL, no translations occur and the Cygwin port
will not understand the native paths and the native Win32 port will
not understand the Cygwin paths.
When its value is a string, it is used by PARSE-NAMESTRING to
translate into the appropriate platform-specific representation,
so that on Cygwin, (PARSE-NAMESTRING "c:/gnu/clisp/")
returns #P"/cygdrive/c/gnu/clisp/",
while on Win32 (PARSE-NAMESTRING "/cygdrive/c/gnu/clisp/")
returns #P"C:/gnu/clisp/".
The initial value is "cygdrive", you should edit
config.lisp to change it.This is especially important for the directory-handling functions.
Table 19.1. The minimum filename syntax that may be used portably
| pathname | meaning |
|---|---|
"xxx" | for a file with name xxx |
"xxx.yy" | for a file with name xxx and type
yy |
".yy" | for a pathname with type yy and no
name or with name .yy and no type,
depending on the value of CUSTOM:*PARSE-NAMESTRING-DOT-FILE*. |
Hereby xxx denotes 1 to 8 characters,
and yy denotes 1 to 3 characters, each of
which being either an alphanumeric character or the underscore
#\_. Other properties of pathname syntax vary between
operating systems.
When a pathname is to be fully specified (no wildcards), that
means that no :WILD, :WILD-INFERIORS is allowed, no wildcard
characters are allowed in the strings, and name EQ NIL may not
be allowed either.
As permitted by the MAKE-PATHNAME specification, the PATHNAME
directory component is canonicalized when the pathname is constructed:
"" and
"." are removed"..",
"*", and "**" are converted
to :UP, :WILD and :WILD-INFERIORS,
respectivelyfoo/../ are
collapsed
Pathname components
hostNILdeviceNILdirectory = (startpoint
. subdirs)| element | values | meaning |
|---|---|---|
startpoint | :RELATIVE | :ABSOLUTE | |
subdirs | () | ( | |
subdir | :WILD-INFERIORS | ** or
..., all subdirectories |
subdir | SIMPLE-STRING,
may contain wildcard characters "?" and
"*" (may also be specified as :WILD) |
nametypeNIL or SIMPLE-STRING, may contain wildcard characters "?" and
"*" (may also be specified as :WILD)
versionNIL or :WILD or :NEWEST
(after merging the defaults)A UNIX filename is split into name and type.
Pathname components
hostNIL or SIMPLE-STRING, wildcard characters may
occur but do not act as wildcardsdeviceNIL or :WILD or A|...|Z
directory = (startpoint
. subdirs)| element | values | meaning |
|---|---|---|
startpoint | :RELATIVE | :ABSOLUTE | |
subdirs | () | ( | |
subdir | :WILD-INFERIORS | ** or
..., all subdirectories |
subdir | SIMPLE-STRING,
may contain wildcard characters "?" and
"*" (may also be specified as :WILD) |
nametypeNIL or SIMPLE-STRING, may contain wildcard characters "?" and
"*" (may also be specified as :WILD)
versionNIL or :WILD or :NEWEST
(after merging the defaults)If host is non-NIL, device must be NIL.
A Win32 filename is split into name and type.
| External notation: | "A:\sub1.typ\sub2.typ\name.typ" |
| using defaults: | "\sub1.typ\sub2.typ\name.typ" |
| or | "name.typ" |
| or | "*:\sub1.typ\**\sub3.typ\x*.lisp" |
| or similar. |
Instead of "\" one may use "/", as usual for DOS
calls.
If host is non-NIL and the directory's startpoint
is not :ABSOLUTE, ( will not be the same as PARSE-NAMESTRING (NAMESTRING
pathname))pathname.
A filename is split into name and type according to the following rule:
"." in the filename, then the
name is everything, type is NIL;".", then name is the part
before and type the part after the last dot.if the only "." is the first character, then
the behavior depends on the value of the user variable
CUSTOM:*PARSE-NAMESTRING-DOT-FILE*
which can be either
Due to this name/type splitting rule, there are pathnames
that cannot result from PARSE-NAMESTRING.
To get a pathname whose type contains a dot or whose name contains a
dot and whose type is NIL, MAKE-PATHNAME must be used. Example:
(.MAKE-PATHNAME :NAME "foo.bar")
The symbol :UNSPECIFIC is not permitted as a
pathname component for any slot of any pathname.
It is also illegal to pass it as an argument to MAKE-PATHNAME,
although it is a legal argument (treated as NIL)
to USER-HOMEDIR-PATHNAME.
The only use for :UNSPECIFIC is that it is
returned by PATHNAME-DEVICE for LOGICAL-PATHNAMEs, as required by
[sec_19-3-2-1].
External notation of pathnames (cf. PARSE-NAMESTRING and
NAMESTRING), of course without spaces, [,],{,}:
[ "/" ] | "/" denotes absolute pathnames |
{ name "/" } | each name is a subdirectory |
[ name ["." type] ] | filename with type (extension) |
Name and type may be STRINGs of any LENGTH
(consisting of printing CHARACTERs, except "/").
[ [drivespec] : ] | a letter "*"|a|...|z|A|...|Z |
{ name [. type] \ } | each name is a subdirectory, "\" may be
replaced by "/" |
[ name [. type] ] | filename with type (extension) |
Name and type may be STRINGs of any LENGTH
(consisting of printing CHARACTERs, except "/",
"\", ":").
No notes.
Pathname Designators. When CUSTOM:*PARSE-NAMESTRING-ANSI* is NIL, SYMBOL is also treated as a
pathname designator,
namely its SYMBOL-NAME is converted to the
operating system's preferred pathname case.
Function PATHNAME-MATCH-P. PATHNAME-MATCH-P does not interpret missing components as
wild.
TRANSLATE-PATHNAMETRANSLATE-PATHNAME accepts three additional keyword arguments:
(TRANSLATE-PATHNAME source
from-wildname
to-wildname &KEY :ALL
:MERGE :ABSOLUTE)
If :ALL is specified and non-NIL, a list of all resulting
pathnames, corresponding to all matches of (, is
returned.PATHNAME-MATCH-P
source from-wildname)
If :MERGE is specified and NIL, unspecified pieces of
to-pathname are not replaced by
corresponding pieces of source.
If :ABSOLUTE is specified and non-NIL, the returned
pathnames are converted to absolute by merging in the current process'
directory, therefore rendering pathnames suitable for the OS and
external programs. So, to pass a pathname to an external program, you
do ( or NAMESTRING (TRANSLATE-PATHNAME pathname
#P"" #P"" :ABSOLUTE T))(.NAMESTRING
(EXT:ABSOLUTE-PATHNAME pathname))
TRANSLATE-LOGICAL-PATHNAMETRANSLATE-LOGICAL-PATHNAME accepts an additional keyword
argument :ABSOLUTE, similar to Section 19.5.1, “Function TRANSLATE-PATHNAME”.
PARSE-NAMESTRING(
returns a logical pathname only if PARSE-NAMESTRING string &OPTIONAL
host defaults &KEY start end
junk-allowed)host is a
logical host
or host is NIL and defaults is a LOGICAL-PATHNAME.
To construct a logical pathname from a string, the function
LOGICAL-PATHNAME can be used.
The [ANSI CL standard] behavior of recognizing logical pathnames when
the string begins with some alphanumeric characters followed by a
colon (#\:) can be very confusing
(cf. "c:/autoexec.bat",
"home:.clisprc" and
"prep:/pub/gnu")
and therefore is disabled by default.
To enable the [ANSI CL standard] behavior, you should set CUSTOM:*PARSE-NAMESTRING-ANSI* to non-NIL.
Note that this also disables treating SYMBOLs as pathname designators.
MERGE-PATHNAMES( returns a
logical pathname only if
MERGE-PATHNAMES pathname
[default-pathname])default-pathname is a LOGICAL-PATHNAME.
To construct a logical pathname from a STRING, the function
LOGICAL-PATHNAME can be used.
When both pathname and default-pathname
are relative pathnames, the behavior depends on CUSTOM:*MERGE-PATHNAMES-ANSI*: when it is
NIL, then CLISP retains its traditional behavior:
(
evaluates to MERGE-PATHNAMES #P"x/" #P"y/")#P"x/"
Rationale. MERGE-PATHNAMES is used to specify default components for
pathnames, so there is some analogy between
( and
MERGE-PATHNAMES a b)(. Obviously, putting in the
same default a second time should do the same as putting it in once:
OR a b)( is the same as OR a b b)(, so
OR a b)(
should be the same as MERGE-PATHNAMES (MERGE-PATHNAMES a b) b)(.
MERGE-PATHNAMES a b)
(This question actually does matter because in Common Lisp there is no distinction between “pathnames with defaults merged-in” and “pathnames with defaults not yet applied”.)
Now, ( and MERGE-PATHNAMES (MERGE-PATHNAMES #P"x/" #P"y/")
#P"y/")( are
MERGE-PATHNAMES #P"x/" #P"y/")EQUAL in CLISP (when CUSTOM:*MERGE-PATHNAMES-ANSI* is NIL), but not in
implementations that strictly follow the [ANSI CL standard].
In fact, the above twice-default = once-default
rule holds for all pathnames in CLISP.
Conversely, when CUSTOM:*MERGE-PATHNAMES-ANSI* is non-NIL, the normal [ANSI CL standard]
behavior is exhibited: (
evaluates to MERGE-PATHNAMES #P"x/" #P"y/")#P"y/x/".
Rationale. “merge” is merge and not or.
LOAD-LOGICAL-PATHNAME-TRANSLATIONSWhen the host argument to LOAD-LOGICAL-PATHNAME-TRANSLATIONS
is not a defined logical host yet, we proceed as follows:
LOGICAL_HOST_host_FROM and
LOGICAL_HOST_host_TO exist, then their values
define the map of the host.LOGICAL_HOST_host exists, its value is read from,
and the result is passed to (SETF
LOGICAL-PATHNAME-TRANSLATIONS).CUSTOM:*LOAD-LOGICAL-PATHNAME-TRANSLATIONS-DATABASE* is consulted.
Its value should be a LIST of files and/or directories,
which are searched for in the CUSTOM:*LOAD-PATHS*, just like for LOAD.
When the element is a file, it is repeatedly READ from,
Allegro CL-style,
odd objects being host names and even object being their
LOGICAL-PATHNAME-TRANSLATIONS.
When the element is a directory, a file, named host
or host.host, in that directory, is READ
from once, CMUCL-style,
the object read being the LOGICAL-PATHNAME-TRANSLATIONS of the
host.EXT:ABSOLUTE-PATHNAME( converts the EXT:ABSOLUTE-PATHNAME pathname)pathname
to a physical pathname, then - if its directory component is not
absolute - converts it to an absolute pathname, by merging in the
current process' directory. This is like TRUENAME, except that it
does not verify that a file named by the pathname exists, not even that
its directory exists. It does no filesystem accesses, except to
determine the current directory. This function is useful when you want
to save a pathname over time, or pass a pathname to an external
program.
CLISP has traditionally taken the view that a directory is a
separate object and not a special kind of file, so whenever the
standard says that a function operates on files
without specifically mentioning that it also works on
directories, CLISP SIGNALs an ERROR when passed a
directory.
CLISP provides separate directory functions, such as
EXT:DELETE-DIRECTORY, EXT:RENAME-DIRECTORY et al.
You can use DIRECTORY or EXT:PROBE-PATHNAME to figure out whether a
given namestring refers to a file or a directory.
EXT:PROBE-PATHNAMEFunction EXT:PROBE-PATHNAME figures out whether the argument refers to
an existing directory or an existing regular file, and returns 4 values
if the filesystem object exists:
or NIL if it does not exist.
E.g., if you have a file file, a directory directory,
a symbolic link link-file pointing to file
and a symbolic link link-dir pointing to directory,
then
(EXT:PROBE-PATHNAME#P"filename") ⇒#P"/.../filename"⇒#P"/.../filename"⇒3427467015⇒3171976(EXT:PROBE-PATHNAME#P"filename/") ⇒#P"/.../filename"⇒#P"/.../filename"⇒3427467015⇒3171976(EXT:PROBE-PATHNAME#P"directory") ⇒#P"/.../directory/"⇒#P"/.../directory/"⇒3426940352⇒1024(EXT:PROBE-PATHNAME#P"directory/") ⇒#P"/.../directory/"⇒#P"/.../directory/"⇒3426940352⇒1024(EXT:PROBE-PATHNAME#P"link-file") ⇒#P"/.../filename"⇒#P"/.../link-file"⇒3427467015⇒3171976(EXT:PROBE-PATHNAME#P"link-file/") ⇒#P"/.../filename"⇒#P"/.../link-file"⇒3427467015⇒3171976(EXT:PROBE-PATHNAME#P"link-dir") ⇒#P"/.../directory/"⇒#P"/.../link-dir/"⇒3426940352⇒1024(EXT:PROBE-PATHNAME#P"link-dir/") ⇒#P"/.../directory/"⇒#P"/.../link-dir/"⇒3426940352⇒1024
PROBE-FILEPROBE-FILE cannot be used to check whether a directory exists.
Use functions EXT:PROBE-DIRECTORY, EXT:PROBE-PATHNAME or DIRECTORY for this.
FILE-AUTHORFILE-AUTHOR always returns NIL, because the operating systems
CLISP is ported to do not store a file's author in the file system.
Some operating systems, such as UNIX, have the notion of a file's
owner, and some other Common Lisp implementations return
the user name of the file owner. CLISP does not do this, because
owner and author are not the
same; in particular, authorship is preserved by copying, while
ownership is not.
Use OS:FILE-OWNER
to find the owner of the file. See also
OS:FILE-PROPERTIES
(Platform Dependent: Win32 platform only.).
DELETE-FILE( deletes the pathname
DELETE-FILE pathname)pathname, not its TRUENAME, and returns the absolute pathname it
actually removed or NIL if pathname did not exist.
When pathname points to a file which is currently open in CLISP,
an ERROR is SIGNALed.
To remove a directory, use EXT:DELETE-DIRECTORY instead.
RENAME-FILEThis functions accepts and extra keyword argument :IF-EXISTS.
When it is :ERROR (the default), an ERROR is SIGNALed if the destination
pathname names an existing file, otherwise (e.g., if it is :OVERWRITE)
the destination file atomically overwritten.
When CUSTOM:*ANSI* is non-NIL, only the standard two arguments are accepted,
and and ERROR is SIGNALed when the destination pathname names an existing file.
This function cannot operate on directories,
use EXT:RENAME-DIRECTORY to rename a directory.
EXT:PROBE-DIRECTORY( tests whether EXT:PROBE-DIRECTORY pathname)pathname exists
and is a directory.
It will, unlike PROBE-FILE or TRUENAME, not SIGNAL an ERROR
if the parent directory of pathname does not exist.
DIRECTORY( can run in two modes:
DIRECTORY &OPTIONAL pathname &KEY
:FULL :CIRCLE :IF-DOES-NOT-EXIST)
pathname contains no name or type component, a
list of all matching directories is produced.
E.g., (DIRECTORY "/etc/*/") lists
all subdirectories in the directory
#P"/etc/".(DIRECTORY "/etc/*") lists all
regular files in the directory #P"/etc/".
If you want all the files and subdirectories in the current directory,
you should use (.
If you want all the files and subdirectories in all the subdirectories
under the current directory (similar to the ls
NCONC (DIRECTORY "*/") (DIRECTORY "*"))-R UNIX command), use
(.NCONC (DIRECTORY "**/") (DIRECTORY "**/*"))
Keyword arguments accepted by DIRECTORY
:FULLNIL, additional
information is returned: for each matching file you get a LIST of
at least four elements (file-pathname
file-truename
file-write-date-as-decoded-time
file-length).
:CIRCLENIL, DIRECTORY avoids
endless loops that may result from symbolic links.
:IF-DOES-NOT-EXISTThis argument controls the treatment of links pointing to non-existent files and can take the following values:
:DISCARD (default):ERRORERROR is SIGNALed on bad directory entries
(this corresponds to the default behavior of DIRECTORY in CMU CL)
:KEEP(DIRECTORY
... :TRUNAMEP NIL) call in CMU CL)
:IGNORE:DISCARD, but also
do not signal an error when a directory is unaccessible (contrary to
the [ANSI CL standard] specification).( is like EXT:DIR &OPTIONAL
pathname)DIRECTORY, but displays the pathnames
instead of returning them. (EXT:DIR)
shows the contents of the current directory.
EXT:DEFAULT-DIRECTORY( is equivalent to EXT:DEFAULT-DIRECTORY)(.
EXT:CD)( is equivalent to
SETF (EXT:DEFAULT-DIRECTORY) pathname)(, except for the return value.EXT:CD pathname)
EXT:DELETE-DIRECTORY(
removes an (empty) subdirectory.EXT:DELETE-DIRECTORY directory)
EXT:RENAME-DIRECTORY( renames a
subdirectory to a new name.EXT:RENAME-DIRECTORY old-directory
new-directory)
Table of Contents
STREAM-EXTERNAL-FORMATSTREAM-ELEMENT-TYPEEXT:MAKE-STREAMFILE-POSITIONEXT:ELASTIC-NEWLINEOPENCLEAR-INPUTCLOSEOPEN-STREAM-PBROADCAST-STREAMEXT:MAKE-BUFFERED-INPUT-STREAM
and EXT:MAKE-BUFFERED-OUTPUT-STREAM
Interactive streams are those whose next input might depend on a prompt one might output.
When run interactively, CLISP creates a single “terminal”
STREAM and binds *TERMINAL-IO* to it.
All other standard streams (*STANDARD-INPUT*, *STANDARD-OUTPUT*
*ERROR-OUTPUT*, *TRACE-OUTPUT*, *QUERY-IO*, *DEBUG-IO*)
are SYNONYM-STREAMs pointing to *TERMINAL-IO*.
This has the benefit of avoiding unwanted blank lines from FRESH-LINE,
see Section 21.6, “Newline Convention”.
However, there may be situations, especially in batch mode,
when one wants to use a C-style i/o where *STANDARD-OUTPUT*
and *ERROR-OUTPUT* point to different OS file descriptor so that they can be
redirected
to files in the command line and examined separately.
Often CLISP can detect such situations (stdout and stderr not being
the terminal) and handle them just as expected.
However, there may be cases when one needs to do something like:
(SETQ*STANDARD-INPUT*(EXT:MAKE-STREAM:INPUT)*STANDARD-OUTPUT*(EXT:MAKE-STREAM:OUTPUT:BUFFEREDT)*ERROR-OUTPUT*(EXT:MAKE-STREAM:ERROR:BUFFEREDT))
in the script or init function.
See also Section 32.1, “Random Screen Access”.
Input through *TERMINAL-IO* uses the GNU readline library.
Arrow keys can be used to move within the input history.
The TAB key completes the SYMBOL name or
PATHNAME that is being typed.
See readline user
manual for general details and
TAB key for CLISP-specific
extensions.
The GNU readline library is not used (even when
CLISP is linked against it) if the stdin and stdout do not both
refer to the same terminal.
This is determined by the function stdio_same_tty_p
in file src/stream.d.
In some exotic cases, e.g., when running under gdb in
an rxvt window under Cygwin, this may be
determined incorrectly.
See also Section 33.4, “Advanced Readline and History Functionality”.
Linking against GNU readline. For CLISP to use GNU readline it has to be detected by the configure process.
If you run it as
$ ./configure --with-readlineit will fail if it cannot find a valid modern GNU readline installation.
--without-readline, it will not even try to
find GNU readline.--with-readline=default) is to use GNU readline if
it is found and link CLISP without it otherwise.
You can find out whether GNU readline has been detected by running
$ grep HAVE_READLINE config.hin your build directory.
EXT:WITH-KEYBOARD*TERMINAL-IO* is not the only stream that
communicates directly with the user: During execution of the body of a
( form,
EXT:WITH-KEYBOARD . body)EXT:*KEYBOARD-INPUT* is the STREAM that reads the
keystrokes from the keyboard.
It returns every keystroke in detail as an SYS::INPUT-CHARACTER with the
following slots (see Section 13.4.1, “Input Characters” for accessing them):
charthe CHARACTER for standard keys
(accessed with CHARACTER)
For non-standard keys CHARACTER SIGNALs an ERROR, use EXT:CHAR-KEY:
(EXT:WITH-KEYBOARD(LOOP:forchar= (READ-CHAREXT:*KEYBOARD-INPUT*) :forkey= (OR(EXT:CHAR-KEYchar) (CHARACTERchar)) :do (LISTcharkey)) :when (EQLkey#\Space) :return (LISTcharkey)))
keythe key name, for non-standard keys
(accessed with EXT:CHAR-KEY):
bits:HYPER:SUPER:CONTROL:METAfont0.
This keyboard input is not echoed on the screen. During execution of a
( form, no input from
EXT:WITH-KEYBOARD . body)*TERMINAL-IO* or any synonymous stream should be requested.
Since SYS::INPUT-CHARACTER is not a subtype of
CHARACTER, READ-LINE on EXT:*KEYBOARD-INPUT* is illegal.
READ-BYTE,
EXT:READ-INTEGER & EXT:READ-FLOATThe function (
reads a multi-byte EXT:READ-INTEGER stream
element-type &OPTIONAL ENDIANNESS eof-error-p eof-value)INTEGER from stream, which should be a
STREAM with STREAM-ELEMENT-TYPE (.
UNSIGNED-BYTE 8)element-type should be type equivalent to (,
where UNSIGNED-BYTE n)n is a multiple of 8.
( is like
EXT:READ-INTEGER stream element-type)( if READ-BYTE stream)stream's
STREAM-ELEMENT-TYPE were set to element-type,
except that stream's FILE-POSITION will increase by
n/8
instead of 1.
Together with (, this
function permits mixed character/binary input from a stream.SETF STREAM-ELEMENT-TYPE)
The function ( reads a
floating-point number in IEEE 754 binary representation from
EXT:READ-FLOAT stream element-type
&OPTIONAL ENDIANNESS eof-error-p eof-value)stream, which should be a STREAM with
STREAM-ELEMENT-TYPE (. UNSIGNED-BYTE 8)element-type should be
type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.
Endianness. ENDIANNESS
can be :LITTLE or :BIG.
The default is :LITTLE, which corresponds
to the READ-BYTE behavior in CLISP.
WRITE-BYTE,
EXT:WRITE-INTEGER & EXT:WRITE-FLOATThe function ( writes a multi-byte EXT:WRITE-INTEGER integer stream element-type
&OPTIONAL ENDIANNESS)INTEGER to
stream, which should be a STREAM with
STREAM-ELEMENT-TYPE (. UNSIGNED-BYTE 8)element-type should be
type equivalent to (, where UNSIGNED-BYTE n)n is a multiple of 8.
( is
like EXT:WRITE-INTEGER integer stream element-type)( if WRITE-BYTE integer stream)stream's
STREAM-ELEMENT-TYPE were set to element-type, except that stream's
FILE-POSITION will increase by
n/8
instead of 1.
Together with (, this
function permits mixed character/binary output to a SETF STREAM-ELEMENT-TYPE)STREAM.
The function ( writes a
floating-point number in IEEE 754 binary representation to
EXT:WRITE-FLOAT float
stream element-type &OPTIONAL ENDIANNESS)stream, which should be a STREAM with STREAM-ELEMENT-TYPE
(. UNSIGNED-BYTE 8)element-type should be
type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.
In addition to READ-SEQUENCE, the following two functions are provided:
EXT:READ-BYTE-SEQUENCE
performs multiple READ-BYTE operations:(
fills the subsequence of EXT:READ-BYTE-SEQUENCE sequence
stream &KEY :START :END :NO-HANG :INTERACTIVE)sequence specified by :START and :END
with INTEGERs consecutively read from stream. It returns the
index of the first element of sequence that was not updated (=
end or < end if the stream reached its end).
When no-hang is non-NIL, it does not block: it treats input
unavailability as end-of-stream. When no-hang is NIL and interactive is
non-NIL, it can block for reading the first byte but does not block
for any further bytes.
This function is especially efficient if sequence is a
( and VECTOR (UNSIGNED-BYTE 8))stream is a file/pipe/socket STREAM
with STREAM-ELEMENT-TYPE (.
UNSIGNED-BYTE 8)
EXT:READ-CHAR-SEQUENCE
performs multiple READ-CHAR operations:( fills the subsequence of EXT:READ-CHAR-SEQUENCE sequence stream &KEY
:START :END)sequence
specified by :START and :END with characters consecutively read
from stream. It returns the index of the first element of
sequence that was not updated (= end or < end if the
stream reached its end).
This function is especially efficient if sequence is a
STRING and stream is a file/pipe/socket STREAM with
STREAM-ELEMENT-TYPE CHARACTER or an input STRING-STREAM.
In addition to WRITE-SEQUENCE, the following two functions are provided:
EXT:WRITE-BYTE-SEQUENCE
performs multiple WRITE-BYTE operations:( outputs
the EXT:WRITE-BYTE-SEQUENCE sequence stream
&KEY :START :END :NO-HANG :INTERACTIVE)INTEGERs of the subsequence of sequence specified by
:START and :END to stream.
When no-hang is non-NIL, does not block.
When no-hang is NIL and interactive is non-NIL, it can
block for writing the first byte but does not block for any further
bytes. Returns two values: sequence and the index of the first
byte that was not output.
This function is especially efficient if sequence is a
( and VECTOR (UNSIGNED-BYTE 8))stream is a file/pipe/socket STREAM with
STREAM-ELEMENT-TYPE (.UNSIGNED-BYTE 8)
EXT:WRITE-CHAR-SEQUENCE
performs multiple WRITE-CHAR operations:( outputs the characters of the subsequence of
EXT:WRITE-CHAR-SEQUENCE sequence stream &KEY
:START :END)sequence specified by :START and :END to stream.
Returns the sequence argument.
This function is especially efficient if sequence is a
STRING and stream is a file/pipe/socket STREAM with
STREAM-ELEMENT-TYPE CHARACTER.
The rationale for EXT:READ-CHAR-SEQUENCE, EXT:READ-BYTE-SEQUENCE, EXT:WRITE-CHAR-SEQUENCE and
EXT:WRITE-BYTE-SEQUENCE is that some STREAMs support both character and binary
i/o, and when you read into a SEQUENCE that can hold both (e.g.,
LIST or SIMPLE-VECTOR) you cannot determine which kind of
input to use. In such situation READ-SEQUENCE and WRITE-SEQUENCE
SIGNAL an ERROR, while EXT:READ-CHAR-SEQUENCE, EXT:READ-BYTE-SEQUENCE, EXT:WRITE-CHAR-SEQUENCE and
EXT:WRITE-BYTE-SEQUENCE work just fine.
In addition to the standard functions LISTEN and
READ-CHAR-NO-HANG, CLISP provides the following functionality
facilitating non-blocking input and output, both binary and
character.
(EXT:READ-CHAR-WILL-HANG-P stream)EXT:READ-CHAR-WILL-HANG-P queries the stream's input status.
It returns NIL if READ-CHAR and PEEK-CHAR with a
peek-type of NIL will return immediately.
Otherwise it returns T. (In the latter case the standard
LISTEN function would return NIL.)
Note the difference with (: When the NOT (LISTEN
stream))end-of-stream is reached, LISTEN returns
NIL, whereas EXT:READ-CHAR-WILL-HANG-P returns NIL.
Note also that EXT:READ-CHAR-WILL-HANG-P is not a good way to test for end-of-stream:
If EXT:READ-CHAR-WILL-HANG-P returns T, this does not mean that the stream will
deliver more characters. It only means that it is not known at this
moment whether the stream is already at end-of-stream, or will deliver
more characters.
(EXT:READ-BYTE-LOOKAHEAD stream)stream's
STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8).
Returns T if READ-BYTE would return immediately with an
INTEGER result.
Returns :EOF if the end-of-stream is already known to be reached.
If READ-BYTE's value is not available immediately, returns NIL
instead of waiting.(EXT:READ-BYTE-WILL-HANG-P stream)stream's
STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8).
Returns NIL if READ-BYTE will return immediately.
Otherwise it returns true.(EXT:READ-BYTE-NO-HANG stream &OPTIONAL
eof-error-p eof-value)stream's
STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8).
Returns an INTEGER or does end-of-stream handling, like READ-BYTE,
if that would return immediately.
If READ-BYTE's value is not available immediately, returns NIL
instead of waiting.LISTEN on binary streamsThe [ANSI CL standard] specification for LISTEN mentions “character
availability” as the criterion that determines the return value.
Since a CHARACTER is never available on a
binary STREAM (i.e., a stream with STREAM-ELEMENT-TYPE being a
subtype of INTEGER), LISTEN returns NIL for such streams.
(You can use SOCKET:SOCKET-STATUS to check binary streams).
Any other behavior would be hard to make consistent: consider a bivalent
stream, i.e., a STREAM that can be operated upon by both
READ-CHAR and READ-BYTE.
What should LISTEN return on such a stream if what is actually available
on the stream at the moment is only a part of a multi-byte character?
Right now one can use first SOCKET:SOCKET-STATUS to check if anything at all is
available and then use LISTEN to make sure that a full CHARACTER
is actually there.
The answer is complicated. There is an antagonism between
the “old Lisp way” of outputting a newline before the
line's contents (exemplified by the functions PRINT and PPRINT) and
the “Unix way” of outputting a newline after the line's
contents. Which one is “right”?
A newline convention is, by definition, a consistent way to use
the TERPRI and FRESH-LINE functions or - in FORMAT notation -
~% and ~& directives in such a way that the
resulting output is properly subdivided into lines.
Three newline conventions are conceivable:
The most important criterion is interoperability. Two newline conventions are interoperable if, when parts of a program use one of the convention and other parts of the program use the other conventions, lines are still properly separated. It is easily seen that A and B are interoperable, B and C are interoperable as well, but A and C are not interoperable: When an output with convention A is followed by output in convention C, two lines are appended without a line separator. This should not happen.
Therefore, in what follows, we consider five kinds of programs:
Which of these five kinds of programs operation is satisfactory? Let us consider different criteria:
FRESH-LINE prints a newline when
it is not needed, i.e. when it cannot tell for sure whether the
current column is 0? (This situation happens, for example, when
logging to a file: After the user has entered a line interactively,
the column on screen is 0, but since the input has not been echoed in
the log file, the column in the log file is usually not 0, and
FRESH-LINE must output a newline. Then a blank
line is visible on the screen.)FRESH-LINE omits a newline when it
would be needed?
(This is more rare, but can happen, for example, when standard output
and standard error are different streams but are joined outside the
Lisp implementation, at the OS level.
Such as in lisp | cat.)Is it possible to reliably output a blank line before or after a paragraph of text? I.e. what happens with
FRESH-LINE, namely a conditional newline that is annullated if the
next output on the stream will be a
newline. (EXT:ELASTIC-NEWLINE, see below.)Each approach has its advantages and disadvantages.
When used globally (i.e. no interoperability requirements), A, B, C can be compared as follows:
For CLISP built-ins, however, the interoperability requirement with both A and C is a major requirement. Therefore we have to choose B, and accept the drawbacks:
And to minimize the drawbacks, we recommend the user programs to use approach B or C, but not A.
Another drawback of B is, however, that in interactive sessions the cursor is nearly always positioned at the beginning of a line, pointing the user's focus to the wrong point and taking away a screen line.
To solve this, we introduce the concept of an elastic
newline, output by the function EXT:ELASTIC-NEWLINE.
This is the converse of FRESH-LINE: It waits for the next character
and outputs a newline when the next character is not a newline; then
the next character is processed normally.
As a FORMAT directive, we write it ~..
EXT:ELASTIC-NEWLINE followed by FRESH-LINE leads to exactly one newline
always.
Elastic newline leads to a slightly different newline convention:
The five programs being considered are now:
FORCE-OUTPUT. This is a general problem with buffered streams;
CLISP's FRESH-LINE contains a workaround that is limited to
*STANDARD-OUTPUT* and *ERROR-OUTPUT*.Now criterium 1 is satisfied perfectly. We therefore choose B', not B, for use inside CLISP, and programs can use either A or C without problems during normal operation.
STREAM-EXTERNAL-FORMATSTREAM-EXTERNAL-FORMAT is SETFable: (,
SETF
(STREAM-EXTERNAL-FORMAT stream [direction]) encoding)direction can be :INPUT, :OUTPUT, or NIL.
If no direction is given, the operation is nonrecursive.
This will not work on *TERMINAL-IO* et al, use CUSTOM:*TERMINAL-ENCODING*
instead.
STREAM-ELEMENT-TYPESTREAM-ELEMENT-TYPE is SETFable. The STREAM-ELEMENT-TYPE of
STREAMs created by the functions OPEN, EXT:MAKE-PIPE-INPUT-STREAM
EXT:MAKE-PIPE-OUTPUT-STREAM, EXT:MAKE-PIPE-IO-STREAM, SOCKET:SOCKET-ACCEPT, SOCKET:SOCKET-CONNECT
can be modified, if the old and the new STREAM-ELEMENT-TYPEs are either
CHARACTER or
(UNSIGNED-BYTE 8) or (SIGNED-BYTE 8); or(UNSIGNED-BYTE n) or (SIGNED-BYTE n), with the
same n.Functions STREAM-ELEMENT-TYPE and ( are SETF
STREAM-ELEMENT-TYPE)GENERIC-FUNCTIONs, see
Chapter 30, Gray streams.
CLISP expects to be able to
do CHARACTER i/o on standard streams like *TERMINAL-IO*,
*STANDARD-OUTPUT*, *STANDARD-INPUT*, *ERROR-OUTPUT*,
*QUERY-IO* et al, thus is is a very bad idea
to change their STREAM-ELEMENT-TYPE even when you can. Use
EXT:MAKE-STREAM instead, see Section 21.8.1, “Binary input from *STANDARD-INPUT*”.
*STANDARD-INPUT*Note that you cannot change STREAM-ELEMENT-TYPE for some
built-in streams, such as terminal streams,
which is normally the value of *TERMINAL-IO*.
Since *STANDARD-INPUT* normally is a SYNONYM-STREAM pointing
to *TERMINAL-IO*, you cannot use READ-BYTE on it.
Since CGI
(Common Gateway Interface) provides the form data for
METHOD="POST" on the stdin,
and the server will not send you an end-of-stream on the end of the data,
you will need to use
(
to determine how much data you should read from EXT:GETENV "CONTENT_LENGTH")stdin.
CLISP will detect that stdin is not a terminal and create a regular
FILE-STREAM which can be passed to (.
To test this functionality interactively,
you will need to open the standard input in the binary mode:
SETF
STREAM-ELEMENT-TYPE)
(let ((buf (MAKE-ARRAY(PARSE-INTEGER(EXT:GETENV"CONTENT_LENGTH")) :element-type '())) (UNSIGNED-BYTE8)WITH-OPEN-STREAM(in (EXT:MAKE-STREAM:INPUT:ELEMENT-TYPE'()) (UNSIGNED-BYTE8)READ-SEQUENCEbuf in)) buf)
EXT:MAKE-STREAMFunction EXT:MAKE-STREAM creates a Lisp stream out of an OS file descriptor:
(EXT:MAKE-STREAM object &KEY :DIRECTION
:ELEMENT-TYPE :EXTERNAL-FORMAT :BUFFERED)
object designates an OS handle (a file descriptor),
and should be one of the following:
:INPUTstdin
(0 on UNIX):OUTPUTstdout
(1 on UNIX):ERRORstderr
(2 on UNIX)STREAMFILE-STREAM or a SOCKET:SOCKET-STREAMWhen there are several Lisp STREAMs backed by the same OS
file descriptor, the behavior may be highly confusing when some of the
Lisp streams are :BUFFERED. Use FORCE-OUTPUT for output STREAMs,
and bulk input for input STREAMs.
The handle is duplicated (with dup),
so it is safe to CLOSE a STREAM returned by EXT:MAKE-STREAM.
FILE-POSITIONFILE-POSITION works on any FILE-STREAM.
FILE-STREAM, its file position is increased by 2 since #\Newline is
encoded as CR/LF in the file.
EXT:ELASTIC-NEWLINEThe function ( is like
EXT:ELASTIC-NEWLINE [stream])FRESH-LINE but the other way around: It outputs a conditional newline
on stream, which is canceled if the next
output on stream happens to be a newline. More precisely, it
causes a newline to be output right before the next character is
written on stream, if this character is not a newline.
The newline is also output if the next operation on the stream is
FRESH-LINE, FINISH-OUTPUT, FORCE-OUTPUT or CLOSE.
The functionality of EXT:ELASTIC-NEWLINE is also available through
the FORMAT directive ~..
A technique for avoiding unnecessary blank lines in output is to
begin each chunk of output with a call to FRESH-LINE and to terminate it
with a call to EXT:ELASTIC-NEWLINE.
See also Section 21.6, “Newline Convention”.
OPENOPEN accepts an additional keyword :BUFFERED.
The acceptable values for the arguments to the
file/pipe/socket STREAM functions
:ELEMENT-TYPEtypes equivalent to CHARACTER or
(, UNSIGNED-BYTE n)(; if the stream is to be
unSIGNED-BYTE n):BUFFERED, n must be a multiple of 8.
If n is not a multiple of 8, CLISP will use the
specified number of bits for i/o, and write the file length
(as a number of n-bit bytes) in the preamble.
This is done to ensure the input/output consistency:
suppose you open a file with :ELEMENT-TYPE of ( and write 7 bytes
(i.e., 21 bit) there.
The underlying OS can do input/output only in whole 8-bit bytes.
Thus the OS will report the size of the file as 3 (8-bit) bytes.
Without the preamble CLISP will have no way to know how many
3-bit bytes to read from this file - 6, 7 or 8.UNSIGNED-BYTE 3)
:EXTERNAL-FORMATEXT:ENCODINGs, (constant) SYMBOLs in the
“CHARSET” package, STRINGs (denoting iconv-based encodings),
the symbol :DEFAULT, and the line terminator keywords
:UNIX, :MAC, :DOS. The default encoding is CUSTOM:*DEFAULT-FILE-ENCODING*.
This argument determines how the lisp CHARACTER data is
converted to/from the 8-bit bytes that the underlying OS uses.
:BUFFEREDNIL, T, or :DEFAULT.
Have CLISP manage an internal buffer for input or output (in
addition to the buffering that might be used by the underlying OS).
Buffering is a known general technique to significantly speed up i/o.
SOCKET:SOCKET-STREAMs and
pipes, :DEFAULT is equivalent to
T on the input side and to NIL on the output side; it you are
transmitting a lot of data then using buffering
will significantly speed up your i/o;:DEFAULT means that buffered file streams will be returned
for regular files and (on UNIX) block-devices, and unbuffered file
streams for special files.
Note that some files, notably those on the /proc
filesystem (on UNIX systems), are actually, despite their innocuous
appearance, special files, so you might need to supply an explicit
:BUFFERED NIL argument for them. Actually, CLISP detects that
the file is a /proc file, so that one is covered,
but there are probably more strange beasts out there!
CUSTOM:*REOPEN-OPEN-FILE*When an already opened file is opened again, and not both the
existing and the new STREAMs are read-only (i.e., :DIRECTION is
:INPUT or :INPUT-IMMUTABLE), the streams can
mess up each other and produce unexpected results.
The user variable CUSTOM:*REOPEN-OPEN-FILE* controls how CLISP
handles the situation and can take 4 values:
CLEAR-INPUTCalling CLEAR-INPUT on a STREAM removes the end-of-stream state,
thus making it available for further input.
This allows reading from a file as it is being appended to, as if with tail -f.
CLOSEFunction CLOSE is a GENERIC-FUNCTION, see
Chapter 30, Gray streams.
When the :ABORT argument is non-NIL, CLOSE will not
SIGNALs an ERROR even when the underlying OS call fails.
GET-OUTPUT-STREAM-STRING returns the same value after
CLOSE as it would before it.
CLOSE on an already closed STREAM does nothing and returns
T.
If you do not CLOSE your STREAM explicitly, it will be
closed at garbage-collection time automatically
(with ().
This is not recommended though because garbage-collection is not deterministic.
Please use CLOSE stream :ABORT T)WITH-OPEN-STREAM etc.
OPEN-STREAM-PFunction OPEN-STREAM-P is a GENERIC-FUNCTION, see
Chapter 30, Gray streams.
BROADCAST-STREAMINPUT-STREAM-P and INTERACTIVE-STREAM-P return false for
BROADCAST-STREAMs.
(EXT:MAKE-BUFFERED-OUTPUT-STREAM
. Returns a buffered output function)STREAM.
function is a FUNCTION expecting one argument, a SIMPLE-STRING.
WRITE-CHAR collects the CHARACTERs in a STRING, until a
newline character is written or FORCE-OUTPUT/FINISH-OUTPUT is called.
Then function is called with a SIMPLE-STRING as argument,
that contains the characters collected so far.
CLEAR-OUTPUT discards the characters collected so far.
(EXT:MAKE-BUFFERED-INPUT-STREAM . Returns a buffered input function
mode)STREAM.
function is a FUNCTION of 0 arguments that returns
either NIL (stands for end-of-stream) or up to three values
string, start, end.
READ-CHAR returns the CHARACTERs of the current string one
after another, as delimited by start and end, which default to
0 and NIL, respectively.
When the string is consumed, function is called again.
The string returned by function should not be changed by the user.
function should copy the string with COPY-SEQ or SUBSEQ before
returning if the original string is to be modified.
mode determines the behavior of LISTEN
when the current string buffer is empty:
NILFILE-STREAM,
i.e. function is calledTend-of-stream, i.e. one can assume that further characters will always
arrive, without calling functionFUNCTIONFUNCTION tells, upon call, if further
non-empty strings are to be expected.
CLEAR-INPUT discards the rest of the current string,
so function will be called upon the next READ-CHAR operation.
Table of Contents
WRITE & WRITE-TO-STRINGPRINT-UNREADABLE-OBJECTCUSTOM:*PRINT-CLOSURE*An additional variable CUSTOM:*PRINT-CLOSURE* controls whether compiled and
interpreted functions (closures) are output in detailed form.
If CUSTOM:*PRINT-CLOSURE* is non-NIL, a readable syntax is used for closures:
This feature is turned off by WITH-STANDARD-IO-SYNTAX because
it is easy to get wrong (see below) and non-portable.
Closures often refer to value cells or other entities from the
lexical environment. The correct operation of a FUNCTION may depend on the access
to the same value cells as some other, related FUNCTIONs.
If you want to WRITE and READ back FUNCTIONs so that their semantics
is preserved, you have to WRITE and READ all FUNCTIONs that share
some structure in the lexical environment together, and you have to
either bind *PRINT-READABLY* to T or use WITH-STANDARD-IO-SYNTAX:
(SETF(VALUESmy-pop my-push) `(LET((storage ())) (VALUES(LAMBDA() (POPstorage)) (LAMBDA(x) (PUSHx storage))))) (LET((pair (READ-FROM-STRING(WITH-STANDARD-IO-SYNTAX(LET((CUSTOM:*PRINT-CLOSURE*T)) (PRIN1-TO-STRING(CONSmy-pop my-push))))))) (SETQmy-pop-1 (CARpair) my-push-1 (CDRpair)))
Note that my-pop and my-push
share environment between themselves but not with
my-pop-1 and my-push-1 which
can be easily seen if you do
(LET((CUSTOM:*PRINT-CLOSURE*T) (*PRINT-CIRCLE*T)) (LISTmy-pop my-push my-pop-1 my-push-1)))
but which is not at all obvious from the usual
#< output.
CUSTOM:*PRINT-CLOSURE* is initially set to NIL.
CUSTOM:*PRINT-RPARS*An additional variable CUSTOM:*PRINT-RPARS* controls
the output of the right (closing) parentheses.
If CUSTOM:*PRINT-RPARS* is non-NIL, closing parentheses which do not fit onto
the same line as the the corresponding opening parenthesis are output
just below their corresponding opening parenthesis, in the same column.
CUSTOM:*PRINT-RPARS* is initially set to NIL.
CUSTOM:*PRINT-INDENT-LISTS*An additional variable CUSTOM:*PRINT-INDENT-LISTS* controls the indentation of
lists that span more than one line.
It specifies by how many characters items within the list will be
indented relative to the beginning of the list.
CUSTOM:*PRINT-INDENT-LISTS* is initially set to 1.
CUSTOM:*PPRINT-FIRST-NEWLINE*An additional variable CUSTOM:*PPRINT-FIRST-NEWLINE* controls
pretty-printing of multi-line objects.
When CUSTOM:*PPRINT-FIRST-NEWLINE* is non-NIL,
and the current line already has some characters on it,
and the next object will be printed on several lines,
and it does not start with a #\Newline,
then a #\Newline is printed before the object.
E.g., when you type (
you want want to see a terse one-line output when FORMAT T "return value: ~S~%" v)v is something
short (like 0 or NIL or T), but you probably want to see
something nice, like
return value: (long list which does not fit on one line)
instead of
return value: (long list which does not fit on one line)
when it does not.
CUSTOM:*PPRINT-FIRST-NEWLINE* has no effect if *PRINT-PRETTY* is NIL.
CUSTOM:*PPRINT-FIRST-NEWLINE* is initially set to T.
In the absence of SYS::WRITE-FLOAT-DECIMAL, floating point numbers
are output in radix 2. This function is defined in floatprint.lisp
and is not available if you run CLISP without a memory image (which
you should never do anyway!)
If *PRINT-READABLY* is true, *READ-DEFAULT-FLOAT-FORMAT*
has no influence on the way FLOATs are printed.
Characters are printed as specified in [ANSI CL standard] using
#\, with one exception: when printer escaping is in effect,
the space character is printed as
“#\Space” when the
variable CUSTOM:*PRINT-SPACE-CHAR-ANSI* is NIL.
When CUSTOM:*PRINT-SPACE-CHAR-ANSI* is non-NIL, it is printed as
“#\ ”; this is how
[ANSI CL standard] specifies it.
Variable CUSTOM:*PRINT-SYMBOL-PACKAGE-PREFIX-SHORTEST*. When CUSTOM:*PRINT-SYMBOL-PACKAGE-PREFIX-SHORTEST* is non-NIL, the package
prefix is not the PACKAGE-NAME but the shortest (nick)name as
returned by EXT:PACKAGE-SHORTEST-NAME. This variable is ignored when
*PRINT-READABLY* is non-NIL.
When *PRINT-READABLY* is true, other vectors are written as
follows: if the ARRAY-ELEMENT-TYPE is T, the syntax
#( is used.
Otherwise, the syntax x1 ... xn)#A( is used.element-type
dimensions contents)
When *PRINT-READABLY* is true, other arrays are written as
follows: if the ARRAY-ELEMENT-TYPE is T, the syntax
is used.
Otherwise, the syntax # rankAcontents#A( is used.element-type dimensions
contents)
As explicitly permitted by this section, specialized BIT and
CHARACTER ARRAYs are printed with the innermost lists generated
by the printing algorithm being instead printed using BIT-VECTOR and
STRING syntax, respectively.
Variable CUSTOM:*PRINT-EMPTY-ARRAYS-ANSI*. Empty ARRAYs, i.e., arrays with no elements and zero
ARRAY-TOTAL-SIZE (because one of its dimensions is zero) are printed
with the readable syntax #A(, unless the variable element-type dimensions
contents)CUSTOM:*PRINT-EMPTY-ARRAYS-ANSI* is
non-NIL, in which case the arrays are printed using the
[ANSI CL standard]-prescribed syntax
which often loses the dimension information.# rankAcontents
Pathnames are printed as follows: If *PRINT-ESCAPE* is NIL,
only the namestring is printed; otherwise it is printed with the
#P syntax, as per the [ANSI CL standard] issue PRINT-READABLY-BEHAVIOR:CLARIFY.
But, if *PRINT-READABLY* is true, we are in trouble as #P is
ambiguous (which is verboten when *PRINT-READABLY* is true), while
being mandated by the [ANSI CL standard].
Therefore, in this case, CLISP's behavior is determined by the value
of CUSTOM:*PRINT-PATHNAMES-ANSI*: when it is NIL, we print pathnames like this:
.
Otherwise, when the variable #-CLISP #P"..."
#+CLISP #S(PATHNAME ...)CUSTOM:*PRINT-PATHNAMES-ANSI* is non-NIL, the
#P notation is used as per [sec_1-5-1-4-1]
“Resolution of Apparent Conflicts in Exceptional Situations”.
The #S notation for PATHNAMEs is used
extensively in the [Common Lisp HyperSpec] (see examples for PATHNAME,
PATHNAMEP, PARSE-NAMESTRING et al), but was decided against, see
PATHNAME-PRINT-READ:SHARPSIGN-P.
When both *PRINT-READABLY* and CUSTOM:*PRINT-PATHNAMES-ANSI* are
non-NIL and the namestring will be parsed to a dissimilar object
(with the current value of CUSTOM:*PARSE-NAMESTRING-DOT-FILE*), an ERROR of type
PRINT-NOT-READABLE is SIGNALed.
The Lisp Pretty Printer implementation is not perfect yet.
PPRINT-LOGICAL-BLOCK does not respect *PRINT-LINES*.
A pprint dispatch table is a CONS
of a SYMBOL *PRINT-PPRINT-DISPATCH* and an association list which maps
types into priorities and print functions.
Their use is strongly discouraged because of the performance issues:
when *PRINT-PPRINT-DISPATCH* is non-trivial and *PRINT-PRETTY*
is non-NIL, printing of every object requires a lookup in the table,
which entails many calls to TYPEP (which cannot be made fast
enough).
FORMATThe additional FORMAT instruction
~!
is similar to ~/, but avoids putting a function name into a
string, thus, even if the function is not interned in the “COMMON-LISP-USER”
package, you might not need to specify the package explicitly.
( is
equivalent to FORMAT stream "~arguments!" function object)(.FUNCALL function stream object
colon-modifier-p
atsign-modifier-p arguments)
The additional FORMAT instruction
~.
is a kind of opposite to ~&: It outputs a conditional
newline, by calling the function EXT:ELASTIC-NEWLINE.
~ outputs n.n-1 newlines
followed by an EXT:ELASTIC-NEWLINE. ~0. does nothing.
FORMAT ~R and FORMAT ~:R can output only
integers in the range |.
The output is in English, according to the American conventions, and
these conventions are identical to the British conventions only in the
range n| <
1066|.n| <
109
FORMAT ~:@C does not output the character itself, only the
instruction how to type the character.
For FORMAT ~E and FORMAT ~G, the value of
*READ-DEFAULT-FLOAT-FORMAT* does not matter if *PRINT-READABLY*
is true.
FORMAT ~T can determine the current column of any
built-in stream.
WRITE & WRITE-TO-STRINGThe functions WRITE and WRITE-TO-STRING have an additional
keyword argument :CLOSURE which is used to bind
CUSTOM:*PRINT-CLOSURE*.
PRINT-UNREADABLE-OBJECTVariable CUSTOM:*PRINT-UNREADABLE-ANSI*. The macro PRINT-UNREADABLE-OBJECT, when invoked without body forms,
suppresses the trailing space if only the type is to be printed, and
suppresses the leading space if only the identity is to be printed. This
behaviour can be turned off set setting the variable CUSTOM:*PRINT-UNREADABLE-ANSI*
to a non-NIL value: in this case, a trailing or leading space are output,
as prescribed by [ANSI CL standard].
*PRINT-CASE* controls the output not only of symbols, but also
of characters and some #<unreadable> objects.
*PRINT-PRETTY* is initially NIL but set to T
in config.lisp. This makes screen output prettier.
*PRINT-ARRAY* is initially set to T.
When the value of ( is
READTABLE-CASE
readtable):INVERT, it applies to the package name and the
symbol name of a symbol separately (not to the entire token at once).
An alternative to the use of READTABLE-CASE is the use of the
:CASE-SENSITIVE option of MAKE-PACKAGE and DEFPACKAGE.
recursive-p argument
[sec_23-1-3-2]When non-NIL recursive-p argument is passed to a top-level READ
call, an ERROR is SIGNALed.
Table of Contents
The compiler can be called not only by the functions COMPILE,
COMPILE-FILE and DISASSEMBLE, but also by the declaration
(COMPILE).
COMPILE-FILECOMPILE-FILE compiles a file to a platform-independent
bytecode:
(COMPILE-FILEfilename&KEY:OUTPUT-FILE:LISTING:EXTERNAL-FORMAT((:WARNINGSCUSTOM:*COMPILE-WARNINGS*)CUSTOM:*COMPILE-WARNINGS*) ((:VERBOSE*COMPILE-VERBOSE*)*COMPILE-VERBOSE*) ((*COMPILE-PRINT*)*COMPILE-PRINT*))
Options for COMPILE-FILE
filename:OUTPUT-FILENIL or T or a pathname designator or an
output STREAM. The default is T.:LISTINGNIL or T or a pathname designator or an
output STREAM. The default is NIL.:EXTERNAL-FORMATEXT:ENCODING of the filename.
:WARNINGS:VERBOSE:PRINTThe variables CUSTOM:*COMPILE-WARNINGS*
,
*COMPILE-VERBOSE*, *COMPILE-PRINT* provide defaults for the
:WARNINGS, :VERBOSE, :PRINT keyword arguments, respectively,
and are bound by COMPILE-FILE to the values of the arguments, i.e.,
these arguments are recursive.
For each input file (default file type: #P".lisp")
the following files are generated:
| File | When | Default file type | Contents |
|---|---|---|---|
| output file | only if :OUTPUT-FILE is not NIL | #P".fas" | can be loaded using the LOAD function |
| auxiliary output file | only if :OUTPUT-FILE is not NIL | #P".lib" | used by COMPILE-FILE when compiling a REQUIRE form referring
to the input file |
| listing file | only if :LISTING is not NIL | #P".lis" | disassembly of the output file |
| C output file | only if :OUTPUT-FILE is not NIL | #P".c" | “FFI”; this file is created only if the source contains “FFI” forms |
COMPILE-FILE-PATHNAMEThe default for the :OUTPUT-FILE argument is
T, which means #P".fas".
REQUIREThe function REQUIRE receives as the optional argument either
a PATHNAME or a LIST of PATHNAMEs: files to be LOADed
if the required module is not already present.
LOAD locationsIn addition to (and before) CUSTOM:*LOAD-PATHS*, REQUIRE tries to
find the file to LOAD in the following locations:
Platform Dependent: Only in CLISP built without configure flag --without-dynamic-modules.
The system-wide external modules directory
(.MERGE-PATHNAMES "dynmod/" CUSTOM:*LIB-DIRECTORY*)
Platform Dependent: Only in CLISP built without configure flag --without-dynamic-modules.
The user external modules directory (
(when MERGE-PATHNAMES
"dynmod/" CUSTOM:*USER-LIB-DIRECTORY*)CUSTOM:*USER-LIB-DIRECTORY* is non-NIL).
REQUIRE was called while LOADing, the
directory with the file being loaded (i.e., (MAKE-PATHNAME
:name NIL :type NIL :defaults *LOAD-TRUENAME*)).
COMPILE-FILEAt compile time, (
forms are treated specially: REQUIRE #P"foo")CUSTOM:*LOAD-PATHS* is searched for
#P"foo.lisp" and #P"foo.lib".
If the latest such file is a #P".lisp", it is compiled;
otherwise the #P".lib" is loaded.
If neither is found, ( is called.REQUIRE #P"foo")
It is a very bad
idea to name your files the same way as CLISP modules
(whether system-supplied
or user-installed)
because then REQUIRE will use different files at compile
and execution times.
The #P".lib" is a “header” file which contains the
constant, variable, inline and macro definitions necessary for
compilation of the files that REQUIRE this file, but not the function
definitions and calls that are not necessary for that.
Thus it is not necessary to either enclose REQUIRE forms in
EVAL-WHEN or to load the required files in the makefiles: if you have
two files, #P"foo.lisp" and #P"bar.lisp", and the
latter requires the former, you can write in your Makefile:
all: foo.fas bar.fas foo.fas: foo.lisp clisp -c foo bar.fas: bar.lisp foo.fas clisp -c bar
instead of the more cumbersome (and slower, since #P".lib"s are
usually smaller and load faster that #P".fas"s):
bar.fas: bar.lisp foo.fas
clisp -i foo -c bar
Thus, you do not need to ( in order
to LOAD #P"foo")(.
If memory is tight, and if COMPILE-FILE #P"bar.lisp")#P"foo.lisp" contains only a few inline
functions, macros, constants or variables, this is a space and time
saver. If #P"foo.lisp" does a lot of initializations or side effects
when being loaded, this is important as well.
LOADLOAD accepts four additional keyword arguments :ECHO,
:COMPILING, :EXTRA-FILE-TYPES, and :OBSOLETE-ACTION.
(LOADfilename&KEY((:VERBOSE*LOAD-VERBOSE*)*LOAD-VERBOSE*) ((*LOAD-PRINT*)*LOAD-PRINT*) ((:ECHOCUSTOM:*LOAD-ECHO*)CUSTOM:*LOAD-ECHO*):IF-DOES-NOT-EXIST((:COMPILINGCUSTOM:*LOAD-COMPILING*)CUSTOM:*LOAD-COMPILING*):EXTRA-FILE-TYPES((:OBSOLETE-ACTIONCUSTOM:*LOAD-OBSOLETE-ACTION*)CUSTOM:*LOAD-OBSOLETE-ACTION*))
:VERBOSELOAD to emit a short message that a file is
being loaded. The default is *LOAD-VERBOSE*, which is initially
T, but can be changed by the -v option.
:PRINTLOAD to print the value of each form. The
default is *LOAD-PRINT*, which is initially NIL, but can be
changed by the -v option.:ECHO*STANDARD-OUTPUT* (normally to the screen). Should there be an
error in the file, you can see at one glance where it is.
The default is CUSTOM:*LOAD-ECHO*
,
which is initially NIL, but can be changed by the -v option.
:COMPILINGCOMPILE-FILE - not written to a file.
The default is CUSTOM:*LOAD-COMPILING*
,
which is initially NIL, but can be changed by the -C option.
:EXTRA-FILE-TYPESSpecifies the LIST of additional file types
considered for loading, in addition to CUSTOM:*SOURCE-FILE-TYPES*
(which is initially ("lisp" "lsp" "cl"))
and CUSTOM:*COMPILED-FILE-TYPES*
(which is initially ("fas")).
When filename does not specify a unique file
(e.g., filename is #P"foo" and both #P"foo.lisp"
and #P"foo.fas" are found in the
CUSTOM:*LOAD-PATHS*), then the newest file is loaded.
:OBSOLETE-ACTIONSpecifies the action to take when loading a
#P".fas" with a different bytecode version from the one
supported by this CLISP version. The possible actions are
:DELETE#P".fas" and proceed as with NIL
:ERRORSIGNAL an ERROR
:COMPILECUSTOM:*LOAD-PATHS*)
and LOAD the resultNIL (default)WARN and look
for another matching file
If no file can be loaded and :IF-DOES-NOT-EXIST is non-NIL, an ERROR is SIGNALed.
The default is CUSTOM:*LOAD-OBSOLETE-ACTION*
,
which is initially NIL.
The variables *LOAD-VERBOSE*, *LOAD-PRINT*,
CUSTOM:*LOAD-OBSOLETE-ACTION*, CUSTOM:*LOAD-COMPILING*, and CUSTOM:*LOAD-ECHO* are bound by LOAD when it
receives a corresponding keyword argument (:VERBOSE, :PRINT,
:OBSOLETE-ACTION, :COMPILING, and :ECHO), i.e., these arguments
are recursive, just like the arguments :WARNINGS, :VERBOSE, and
:PRINT for COMPILE-FILE.
When evaluation of a read form SIGNALs an ERROR, three RESTARTs are
available:
SKIPRETRYSTOPVariable CUSTOM:*LOAD-PATHS*. The variable CUSTOM:*LOAD-PATHS* contains a list of directories where the
files are looked for - in addition to the specified or current
directory - by LOAD, REQUIRE, COMPILE-FILE and
LOAD-LOGICAL-PATHNAME-TRANSLATIONS.
*FEATURES*The variable *FEATURES* initially contains the following symbols
Default *FEATURES*
:CLISP:ANSI-CL:COMMON-LISP:INTERPRETEREVAL is implemented:COMPILERCOMPILE and COMPILE-FILE are implemented
:SOCKETS:MT:GENERIC-STREAMS:LOGICAL-PATHNAMES:FFI:GETTEXT:UNICODE:LOOPLOOP form is implemented
:CLOS:MOP:WORD-SIZE=64:WIN32hardware = PC (clone) and operating system = Win32
(Windows 95/98/Me/NT/2000/XP):PC386hardware = PC (clone). It can be used as an
indicator for the mainstream hardware characteristics (such as the
existence of a graphics card with a non-graphics text mode,
or the presence of a keyboard with arrows and
Insert/Delete keys,
or an ISA/VLB/PCI bus) or software characteristics (such as the
Control+Alternate+Delete keyboard
combination).:UNIXoperating system = UNIX (in this case the hardware is irrelevant!)
:BEOSoperating system = BeOS (in that case :UNIX is also present)
:CYGWIN:UNIX is also present)
:MACOSoperating system = Mac OS X (in that case :UNIX is also present)
Each module should add the appropriate keyword, e.g.,
:SYSCALLS,
:DIRKEY,
:REGEXP,
:PCRE, etc.
EXT:FEATUREP
[CLRFI-1](EXT:FEATUREP provides run-time access to
the read-time conditionals form)#+ and #-.
form is a feature exression.
EXT:COMPILED-FILE-P
[CLRFI-2]( returns non-EXT:COMPILED-FILE-P filename)NIL
when the file filename exists, is readable, and appears to be a
CLISP-compiled #P".fas" file compatible with the currently used
bytecode format.
System definition facilities (such as asdf or defsystem) can
use it to determine whether the file needs to be recompiled.
Table of Contents
The debugger may be invoked through the functions
INVOKE-DEBUGGER, BREAK, SIGNAL, ERROR, CERROR, WARN.
The stepper is invoked through the macro STEP.
Debugger and stepper execute subordinate read-eval-print loop
(called break loops)
which are similar to the main read-eval-print loop except for the
prompt and the set of available commands.
Commands must be typed literally, in any case,
without surrounding quotes or whitespace.
Each command has a keyword abbreviation,
indicated in the second column.
Table 25.2. Commands common to the debugger and the stepper
| command | abbreviation | operation |
|---|---|---|
| Abort | :a | abort to the next most recent read-eval-print loop |
| Unwind | :uw | abort to the next most recent read-eval-print loop |
| Quit | :q | quit to the top read-eval-print loop |
The stack is organized into frames and other stack elements.
Usually every invocation of an interpreted function and every
evaluation of an interpreted form corresponds to one stack frame.
Special forms such as LET, LET*, UNWIND-PROTECT and CATCH
produce special kinds of stack frames.
In a break loop there is a current stack frame, which is initially the most recent stack frame but can be moved using the debugger commands Up and Down.
Evaluation of forms in a break loop occurs in the lexical environment of the current stack frame and at the same time in the dynamic environment of the debugger's caller. This means that to inspect or modify a lexical variable all you have to do is to move the current stack frame to be just below the frame that corresponds to the form or the function call that binds that variable.
There is a current stack mode which defines in how much detail the stack is shown by the stack-related debugger commands:
EVAL and APPLY frames are considered.
Every evaluation of a form in the interpreter corresponds to an
EVAL frame. This is the default.APPLY frames are considered.
Every invocation of an interpreted function corresponds to one
APPLY frame.Table 25.3. Commands common to the debugger and the stepper
| command | abbreviation | operation |
|---|---|---|
| Error | :e | print the last error object. |
| Inspect | :i | INSPECT the last error object. |
| Where | :w | shows the current stack frame. |
| Up | :u | goes up one frame, i.e., to the caller if in mode-5 |
| Down | :d | does down one frame, i.e., to the callee if in mode-5 |
| Top | :t | goes to top frame, i.e., to the top-level form if in mode-4 |
| Bottom | :b | goes to bottom (most recent) frame, i.e., most probably to the form or function that caused the debugger to be entered. |
Mode mode | :m mode | sets the current stack mode |
Frame-limit l | :fl | set the frame-limit: this many frames will be printed by Backtrace at most. |
Backtrace [mode [l]] | :bt [mode [l]] | lists the stack in the given mode, bottom frame first, top
frame last; at most l frames are printed. |
If the current stack frame is an EVAL or APPLY frame, the
following commands are available as well:
Table 25.4. Commands specific to EVAL/APPLY
| command | abbreviation | operation |
|---|---|---|
| Break+ | :br+ | sets a breakpoint in the current frame. When the corresponding
form or function will be left, the debugger will be entered again, with
the variable EXT:*TRACE-VALUES* containing a list of its values. |
| Break- | :br- | removes a breakpoint from the current frame. |
| Redo | :rd | re-evaluates the corresponding form or function call. This command can be used to restart parts of a computation without aborting it entirely. |
Return value | :rt value | leaves the current frame, returning the given value. |
Table 25.5. Commands specific to the debugger
| command | abbreviation | operation |
|---|---|---|
| Continue | :c | continues evaluation of the program. |
Table 25.6. Commands specific to the stepper
| command | abbreviation | operation |
|---|---|---|
| Step | :s | step into a form: evaluate this form in single step mode |
| Next | :n | step over a form: evaluate this form at once |
| Over | :o | step over this level: evaluate at once up to the next return |
| Continue | :c | switch off single step mode, continue evaluation |
The stepper is usually used like this: If some form returns a
strange value or results in an error, call ( and navigate using the
commands Step and Next until you
reach the form you regard as responsible. If you are too fast (execute
Next once and get the error), there is no way back;
you have to restart the entire stepper session. If you are too slow
(stepped into a function or a form which certainly is OK), a couple of
Next commands or one Over command
will help.STEP
form)
You can set CUSTOM:*USER-COMMANDS* to a list of
FUNCTIONs, each returning a LIST
of bindings, i.e., either a
E.g.,
(setq CUSTOM:*USER-COMMANDS*
(list (lambda () (list (format nil "~2%User-defined commands:")))
(lambda ()
(flet ((panic (argline)
(format t "don't panic~@[ because of ~A~], ~D~%"
(and (plusp (length argline)) argline)
(random 42))))
(list (format nil "~%panic :p hit the panic button!")
(cons "panic" #'panic)
(cons ":p" #'panic))))
(lambda ()
(let ((curses #("ouch" "yuk" "bletch")))
(flet ((swear (argline)
(format t "~A: ~A!~%" argline
(aref curses (random (length curses))))))
(list (format nil "~%swear :e curse")
(cons "swear" #'swear)
(cons ":e" #'swear)))))))
List of Examples
DISASSEMBLEDISASSEMBLE can disassemble to machine code,
provided that GNU gdb is present. In that case the argument may be a
EXT:SYSTEM-FUNCTION, a FFI:FOREIGN-FUNCTION, a
special operator handler, a SYMBOL denoting one of these, an
INTEGER (address), or a STRING.
EXT:UNCOMPILEThe function EXT:UNCOMPILE does the converse of
COMPILE: ( reverts a compiled
EXT:UNCOMPILE function)function (name), that has been entered or loaded in the same session
and then compiled, back to its interpreted form.
DOCUMENTATIONNo on-line documentation is available for the system functions
(yet), but see Section 25.2.4, “Function DESCRIBE”.
DESCRIBEWhen CUSTOM:*BROWSER* is non-NIL, and CUSTOM:CLHS-ROOT returns a valid URL,
DESCRIBE on a standard Common Lisp symbol will point your web browser to the
appropriate [Common Lisp HyperSpec] page.
Also, when CUSTOM:*BROWSER* is non-NIL, and CUSTOM:IMPNOTES-ROOT returns a
valid URL, DESCRIBE on symbols and packages documented in these
implementation notes will point your web browser to the appropriate
page.
To do this, DESCRIBE will retrieve the appropriate tables from
CUSTOM:CLHS-ROOT and CUSTOM:IMPNOTES-ROOT on the first relevant invocation.
These operations are logged to CUSTOM:*HTTP-LOG-STREAM*.
Function CUSTOM:CLHS-ROOT. Function CUSTOM:CLHS-ROOT is defined in config.lisp. By default it
looks at ( and EXT:GETENV "CLHSROOT")CUSTOM:*CLHS-ROOT-DEFAULT*,
but you may redefine it in config.lisp or RC file.
The return value should be a STRING terminated with a "/",
e.g., http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/ or /usr/doc/HyperSpec/.
If the return value is NIL, the feature is completely disabled.
CUSTOM:*CLHS-ROOT-DEFAULT* is initialized in config.lisp based on
the --hyperspec passed to the top-level configure
script when CLISP was built.
Function CUSTOM:IMPNOTES-ROOT. Function CUSTOM:IMPNOTES-ROOT is defined in config.lisp. By default it
looks at ( and EXT:GETENV "IMPNOTES")CUSTOM:*IMPNOTES-ROOT-DEFAULT*,
but you may redefine it in config.lisp or RC file.
The return value should be a STRING terminated with a "/",
e.g., http://clisp.cons.org/impnotes/, or the path to
the monolithic page, e.g., http://clisp.cons.org/impnotes.html
or /usr/doc/clisp/impnotes.html.
If the return value is NIL, the feature is completely disabled.
TRACEList of Examples
( makes the
functions TRACE function-name ...)function-name, ... traced. Each function-name should be either
a function name or a LIST (, wherefunction-name &KEY
:SUPPRESS-IF :MAX-DEPTH
:STEP-IF :BINDINGS
:PRE :POST
:PRE-BREAK-IF :POST-BREAK-IF
:PRE-PRINT :POST-PRINT
:PRINT)
:SUPPRESS-IF formform is true
:MAX-DEPTH form(>
*trace-level* form). This is useful for tracing functions that
are use by the tracer itself, such as PRINT-OBJECT, or otherwise when
tracing would lead to an infinite recursion.
:STEP-IF formform is true
:BINDINGS
((variable form)...)variables to the result of evaluation of
forms around evaluation of all of the following forms
:PRE formform before calling the function
:POST formform after return from the function
:PRE-BREAK-IF formform is true:POST-BREAK-IF formform is true:PRE-PRINT formform before calling the
function:POST-PRINT formform after return from the
function:PRINT formform both before calling
and after return from the functionIn all these forms you can access the following variables:
EXT:*TRACE-FUNCTION*EXT:*TRACE-ARGS*EXT:*TRACE-FORM*EXT:*TRACE-VALUES*
and you can leave the function call with specified values by using
RETURN.
TRACE and UNTRACE are also applicable to functions
( and to macros, but not to
locally defined functions and macros.SETF symbol)
TRACE prints this line before evaluating the form:
and after evaluating the form it prints:
trace level. Trace: form
where “trace level” is the total nesting level.
trace level. Trace: function-name ==> result
CUSTOM:*TRACE-INDENT*If you want the TRACE level to be indicated by the indentation
in addition to the printed numbers, set CUSTOM:*TRACE-INDENT* to non-NIL.
Initially it is NIL since many nested traced calls will easily
exhaust the available line length.
Example 25.1. Identifying Individual Calls in TRACE
Suppose the trace level above is not enough for you to identify individual calls. You can give each call a unique id and print it:
(defun f0 (x)
(cond ((zerop x) 1)
((zerop (random 2)) (* x (f0 (1- x))))
(t (* x (f1 (1- x))))))
⇒ F0
(defun f1 (x)
(cond ((zerop x) 1)
((zerop (random 2)) (* x (f0 (1- x))))
(t (* x (f1 (1- x))))))
⇒ F1
(defvar *f0-call-count* 0)
⇒ *F0-CALL-COUNT*
(defvar *id0*)
⇒ *ID0*
(defvar *cc0*)
⇒ *CC0*
(defvar *f1-call-count* 0)
⇒ *F1-CALL-COUNT*
(defvar *id1*)
⇒ *ID1*
(defvar *cc1*)
⇒ *CC1*
(trace (f0 :bindings ((*cc0* (incf *f0-call-count*))
(*id0* (gensym "F0-")))
:pre-print (list 'enter *id0* *cc0*)
:post-print (list 'exit *id0* *cc0*))
(f1 :bindings ((*cc1* (incf *f1-call-count*))
(*id1* (gensym "F1-")))
:pre-print (list 'enter *id1* *cc1*)
:post-print (list 'exit *id1* *cc1*)))
;; Tracing function F0.
;; Tracing function F1.
⇒ (F0 F1)
(f0 10)
1. Trace: (F0 '10)
(ENTER #:F0-2926 1)
2. Trace: (F1 '9)
(ENTER #:F1-2927 1)
3. Trace: (F0 '8)
(ENTER #:F0-2928 2)
4. Trace: (F1 '7)
(ENTER #:F1-2929 2)
5. Trace: (F1 '6)
(ENTER #:F1-2930 3)
6. Trace: (F1 '5)
(ENTER #:F1-2931 4)
7. Trace: (F1 '4)
(ENTER #:F1-2932 5)
8. Trace: (F0 '3)
(ENTER #:F0-2933 3)
9. Trace: (F1 '2)
(ENTER #:F1-2934 6)
10. Trace: (F0 '1)
(ENTER #:F0-2935 4)
11. Trace: (F1 '0)
(ENTER #:F1-2936 7)
(EXIT #:F1-2936 7)
11. Trace: F1 ==> 1
(EXIT #:F0-2935 4)
10. Trace: F0 ==> 1
(EXIT #:F1-2934 6)
9. Trace: F1 ==> 2
(EXIT #:F0-2933 3)
8. Trace: F0 ==> 6
(EXIT #:F1-2932 5)
7. Trace: F1 ==> 24
(EXIT #:F1-2931 4)
6. Trace: F1 ==> 120
(EXIT #:F1-2930 3)
5. Trace: F1 ==> 720
(EXIT #:F1-2929 2)
4. Trace: F1 ==> 5040
(EXIT #:F0-2928 2)
3. Trace: F0 ==> 40320
(EXIT #:F1-2927 1)
2. Trace: F1 ==> 362880
(EXIT #:F0-2926 1)
1. Trace: F0 ==> 3628800
⇒ 3628800
*f0-call-count*
⇒ 4
*f1-call-count*
⇒ 7INSPECTThe function INSPECT accepts a keyword argument
:FRONTEND, which specifies the way CLISP will
interact with the user, and defaults
to CUSTOM:*INSPECT-FRONTEND*.
Available :FRONTENDs for
INSPECT in CLISP
:TTY*TERMINAL-IO*
stream. Please use the help command to get the list of all
available commands.:HTTPA window in your Web browser (specified by the
:BROWSER keyword argument) is opened and it is controlled by
CLISP via a SOCKET:SOCKET-STREAM, using the HTTP protocol.
You should be able to use all the standard browser features.
Since CLISP is not multitasking at this time, you will not
be able to do anything else during an INSPECT session. Please click on
the quit link to terminate the session.
Please be aware though, that once you terminate an INSPECT
session, all links in all INSPECT windows in your browser will become
obsolete and using them in a new INSPECT session will result in
unpredictable behavior.
The function INSPECT also accepts a keyword argument :BROWSER,
which specifies the browser used by the :HTTP
front-end and defaults to CUSTOM:*INSPECT-BROWSER*.
The function INSPECT binds some
pretty-printer variables:
| Variable | Bound to |
|---|---|
*PRINT-LENGTH* | CUSTOM:*INSPECT-PRINT-LENGTH* |
*PRINT-LEVEL* | CUSTOM:*INSPECT-PRINT-LEVEL* |
*PRINT-LINES* | CUSTOM:*INSPECT-PRINT-LINES* |
User variable
CUSTOM:*INSPECT-LENGTH*
specifies the number of sequence elements or slots printed in detail
when a sequence or a structure or a CLOS object is inspected.
TIMEThe timing data printed by the macro TIME includes:
GET-INTERNAL-REAL-TIME),GET-INTERNAL-RUN-TIME),The macro EXT:TIMES
(mnemonic:
“TIME and Space”)
is like the macro TIME: ( evaluates the
EXT:TIMES form)form, and, as a side effect, outputs detailed information about the
memory allocations caused by this evaluation. It also prints
everything printed by TIME.
EDThe function ED calls the external editor specified by the value of
( or, failing that, the value of the variable
EXT:GETENV "EDITOR")CUSTOM:*EDITOR*
(set in config.lisp).
If the argument is a function name which was defined in the current
session (not loaded from a file), the program text to be edited is a
pretty-printed version (without comments) of the text which was used to
define the function.
APROPOS & APROPOS-LISTThe search performed by APROPOS and APROPOS-LIST is
case-insensitive.
Variable CUSTOM:*APROPOS-DO-MORE*. You can make APROPOS print more information about the symbols it
found by setting CUSTOM:*APROPOS-DO-MORE* to a list containing some of
:FUNCTION, :VARIABLE, :TYPE, and :CLASS
or just set it to T to get all of the values.
Variable CUSTOM:*APROPOS-MATCHER*. You can make APROPOS and APROPOS-LIST be more flexible in
their search by setting CUSTOM:*APROPOS-MATCHER* to a FUNCTION of one
argument, a pattern (a STRING), returning a new FUNCTION of one
argument, a SYMBOL name (also a STRING),
which returns non-NIL when the symbol name matches the pattern
for the purposes of APROPOS.
When CUSTOM:*APROPOS-MATCHER* is NIL, SEARCH is used.
Some modules come with functions which can be used for
CUSTOM:*APROPOS-MATCHER*, e.g., REGEXP:REGEXP-MATCHER,
WILDCARD:WILDCARD-MATCHER,
PCRE:PCRE-MATCHER.
DRIBBLEIf DRIBBLE is called with an argument, and dribbling is already
enabled, a warning is printed, and the new dribbling request is
ignored.
Dribbling is implemented via a kind (but not a recognizable subtype)
of TWO-WAY-STREAM, named EXT:DRIBBLE-STREAM.
If you have a source bidirectional STREAM x and you want all transactions
(input and output) on x to be copied to the target output STREAM y,
you can do
(DEFVAR*loggable*x) (SETQx(MAKE-SYNONYM-STREAM'*loggable*)) (DEFUNtoggle-logging (&OPTIONALs) (MULTIPLE-VALUE-BIND(source target) (dribble-toggle *loggable* s) (WHEN(STREAMPsource) (SETQ*loggable* source)) target)) (toggle-loggingy) ; start logging ... (toggle-logging) ; finish logging ... (toggle-loggingy) ; restart logging ... (toggle-logging) ; finish logging (CLOSEy)
(EXT:DRIBBLE-STREAM stream)stream is a EXT:DRIBBLE-STREAM, returns two values:
the source and the target streams. Otherwise returns NIL.
(EXT:DRIBBLE-STREAM-P stream)stream is a EXT:DRIBBLE-STREAM, returns T, otherwise
returns NIL.
(EXT:DRIBBLE-STREAM-SOURCE stream)stream is a EXT:DRIBBLE-STREAM, returns its
source stream, otherwise signals a TYPE-ERROR.
(EXT:DRIBBLE-STREAM-TARGET stream)stream is a EXT:DRIBBLE-STREAM, returns its
target stream, otherwise signals a TYPE-ERROR.
(EXT:MAKE-DRIBBLE-STREAM
source target)EXT:DRIBBLE-STREAM.
(EXT:DRIBBLE-TOGGLE stream
&OPTIONAL pathname)stream is a EXT:DRIBBLE-STREAM and pathname is NIL,
writes a dribble termination note to the stream's target
STREAM and returns stream's source and target
STREAMs;
when stream is not a EXT:DRIBBLE-STREAM and pathname is non-NIL,
creates a new EXT:DRIBBLE-STREAM, dribbling from stream to pathname,
writes a dribble initialization note to pathname,
and return the EXT:DRIBBLE-STREAM (the second value is the target STREAM);
otherwise WARN that no appropriate action may be taken.
pathname may be an open output STREAM or a pathname designator.
See above for the sample usage.
See also src/dribble.lisp in
the CLISP source tree.
DRIBBLEDRIBBLE works by operating on *TERMINAL-IO*,
thus is does not work when CLISP acts as a script interpreter
(see Section 32.6.2, “Scripting with CLISP”).
Traditionally, Common Lisp implementations set *STANDARD-INPUT*,
*STANDARD-OUTPUT*, and *ERROR-OUTPUT* to a SYNONYM-STREAM
pointing to *TERMINAL-IO*, and CLISP is no exception.
Thus changing *TERMINAL-IO* to a dribble stream affects all
standard i/o.
On the other hand, when CLISP acts as a script interpreter, it
adheres to the UNIX <stdio.h> conventions,
thus *STANDARD-INPUT*, *STANDARD-OUTPUT*, and
*ERROR-OUTPUT* are normal FILE-STREAMs,
and thus are not affected by DRIBBLE (*TERMINAL-IO* - and
thus ( - is still affected).
The [ANSI CL standard] explicitly permits this behavior by stating
PRINT ... T)
DRIBBLEis intended primarily for interactive debugging; its effect cannot be relied upon when used in a program.
ROOMThe function ROOM
returns five values:
INTERNAL-TIME-UNITS-PER-SECOND)
spent collecting garbageThis function starts a global garbage-collection and returns the same values
as ROOM.
When the optional parameter is non-NIL also invalidates
just-in-time compiled objects.
SHORT-SITE-NAME, LONG-SITE-NAME
should be defined in a site-specific config.lisp file.
The default implementations try to read the value of the environment variable
ORGANIZATION, and, failing that,
call uname.
SHORT-SITE-NAME, LONG-SITE-NAME
should be defined in a site-specific config.lisp file.
The default implementations try to read the registry.
MACHINE-TYPE, MACHINE-VERSION,
MACHINE-INSTANCE and SHORT-SITE-NAME, LONG-SITE-NAME should be
defined by every user in his user-specific config.lisp file.
LISP-IMPLEMENTATION-VERSIONLISP-IMPLEMENTATION-VERSION returns
the numeric version (like 3.14), and
the release date (like "1999-07-21").
When running on the same machine on which CLISP was built, it appends
the binary build and memory image dump date in universal time
(like 3141592654).
When running on a different machine, it appends the MACHINE-INSTANCE
of the machine on which it was built.
EXT:ARGVThis function will return a fresh SIMPLE-VECTOR of
STRING command line arguments passed to the runtime, including
those already processed by CLISP.
Use EXT:*ARGS* instead of this function to get the arguments for your program.
Default Time Zone
CUSTOM:*DEFAULT-TIME-ZONE*
contains the default time zone used by ENCODE-UNIVERSAL-TIME and
DECODE-UNIVERSAL-TIME. It is initially set to -1
(which means 1 hour east of Greenwich, i.e., Mid European Time).
The time zone in a decoded time does not necessarily have be an
INTEGER, but (as FLOAT or RATIONAL number)
it should be a multiple of 1/3600.
GET-INTERNAL-RUN-TIME returns the amount of run time
consumed by the current CLISP process since its startup.
No notes.
No notes.
This is the list of [ANSI CL standard] issues and their current status in CLISP, i.e., whether CLISP supports code that makes use of the functionality specified by the vote.
X3J13 Issues
CALL-NEXT-METHOD in compiled code (items 11,12)
QUOTE).~F, ~E,
~G, ~$ also bind *PRINT-BASE* to 10 and
*PRINT-RADIX* to NILTHE, no for APPLY (spec not clear)
CUSTOM:*PARSE-NAMESTRING-ANSI* is non-NIL
CUSTOM:*PARSE-NAMESTRING-ANSI* is non-NIL
CUSTOM:*SEQUENCE-COUNT-ANSI* is non-NIL;
otherwise negative :COUNT values are not allowed.
READ-DELIMITED-LIST still
constructs a LISTTable of Contents
Table of Contents
DEFCLASSCLASS-NAMECLOS:CLASS-DIRECT-SUPERCLASSESCLOS:CLASS-DIRECT-SLOTSCLOS:CLASS-DIRECT-DEFAULT-INITARGSCLOS:CLASS-PRECEDENCE-LISTCLOS:CLASS-DIRECT-SUBCLASSESCLOS:CLASS-SLOTSCLOS:CLASS-DEFAULT-INITARGSCLOS:CLASS-FINALIZED-PCLOS:CLASS-PROTOTYPE(SETF CLASS-NAME)CLOS:ENSURE-CLASSCLOS:ENSURE-CLASS-USING-CLASSCLOS:FINALIZE-INHERITANCEMAKE-INSTANCEALLOCATE-INSTANCECLOS:VALIDATE-SUPERCLASSCLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGSCLOS:DIRECT-SLOT-DEFINITION-CLASSCLOS:COMPUTE-CLASS-PRECEDENCE-LISTCLOS:COMPUTE-SLOTSCLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITIONCLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGSCLOS:EFFECTIVE-SLOT-DEFINITION-CLASSCLOS:COMPUTE-DEFAULT-INITARGSCLOS:GENERIC-FUNCTION-NAMECLOS:GENERIC-FUNCTION-METHODSCLOS:GENERIC-FUNCTION-LAMBDA-LISTCLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDERCLOS:GENERIC-FUNCTION-DECLARATIONSCLOS:GENERIC-FUNCTION-METHOD-CLASSCLOS:GENERIC-FUNCTION-METHOD-COMBINATION(SETF CLOS:GENERIC-FUNCTION-NAME)ENSURE-GENERIC-FUNCTIONCLOS:ENSURE-GENERIC-FUNCTION-USING-CLASSADD-METHODREMOVE-METHODCLOS:COMPUTE-APPLICABLE-METHODSCLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSESCLOS:COMPUTE-EFFECTIVE-METHODCLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTIONCLOS:MAKE-METHOD-LAMBDACLOS:COMPUTE-DISCRIMINATING-FUNCTIONCLOS:STANDARD-INSTANCE-ACCESSCLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESSCLOS:SET-FUNCALLABLE-INSTANCE-FUNCTIONCLOS:SLOT-VALUE-USING-CLASS(SETF CLOS:SLOT-VALUE-USING-CLASS)CLOS:SLOT-BOUNDP-USING-CLASSCLOS:SLOT-MAKUNBOUND-USING-CLASSThe CLOS specification ([ANSI CL standard] Chanpter 7) describes the standard Programmer Interface for the Common Lisp Object System (CLOS). This document extends that specification by defining a metaobject protocol for CLOS - that is, a description of CLOS itself as an extensible CLOS program. In this description, the fundamental elements of CLOS programs (classes, slot definitions, generic functions, methods, specializers and method combinations) are represented by first-class objects. The behavior of CLOS is provided by these objects, or, more precisely, by methods specialized to the classes of these objects.
Because these objects represent pieces of CLOS programs, and because their behavior provides the behavior of the CLOS language itself, they are considered meta-level objects or metaobjects. The protocol followed by the metaobjects to provide the behavior of CLOS is called the CLOS “Metaobject Protocol” (MOP).
The description of functions follows the same form as used in the CLOS specification. The description of generic functions is similar to that in the CLOS specification, but some minor changes have been made in the way methods are presented.
The following is an example of the format for the syntax description of a generic function:
(gf1xy&OPTIONALv&KEYk)
This description indicates that gf1 is a
generic function with two required parameters, x and y, an
optional parameter v and a keyword parameter k.
The description of a generic function includes a description of its behavior. This provides the general behavior, or protocol of the generic function. All methods defined on the generic function, both portable and specified, must have behavior consistent with this description.
Every generic function described here is an instance of the class
STANDARD-GENERIC-FUNCTION and uses the STANDARD method
combination.
The description of a generic function also includes descriptions of the specified methods for that generic function. In the description of these methods, a method signature is used to describe the parameters and parameter specializers of each method. The following is an example of the format for a method signature:
(gf1 (x CLASS) y &OPTIONAL v &KEY k)
This signature indicates that this primary method on the generic
function gf1 has two required parameters, named
x and y. In addition, there is an optional parameter v and
a keyword parameter k. This signature also indicates that the
method's parameter specializers are the classes CLASS and T.
The description of each method includes a description of the behavior particular to that method.
An abbreviated syntax is used when referring to a method defined
elsewhere in the document. This abbreviated syntax includes the name of
the generic function, the qualifiers, and the parameter specializers. A
reference to the method with the signature shown above is written as:
.
gf1 (CLASS T)
The package exporting the Meta-Object Protocol symbols is unspecified.
The symbols specified by the Meta-Object Protocol are
exported from the package “CLOS” and EXT:RE-EXPORTed from the package
“EXT”.
The package exporting the Meta-Object Protocol symbols is different in other implementations: In SBCL it is the package “SB-MOP”; in OpenMCL it is the package “OPENMCL-MOP”.
For each kind of program element there is a corresponding
basic metaobject class
.
These are the classes: CLASS, CLOS:SLOT-DEFINITION,
GENERIC-FUNCTION, METHOD and METHOD-COMBINATION.
A metaobject class
is a subclass of exactly one of these classes.
The results are undefined if an attempt is made to define a CLASS
that is a subclass of more than one basic metaobject class.
A metaobject is an instance of a metaobject class.
Each metaobject represents one program element. Associated with
each metaobject is the information required to serve its role. This
includes information that might be provided directly in a user interface
macro such as DEFCLASS or DEFMETHOD. It also includes information
computed indirectly from other metaobjects such as that computed from
class inheritance or the full set of methods associated with a generic
function.
Much of the information associated with a metaobject is in the form of connections to other metaobjects. This interconnection means that the role of a metaobject is always based on that of other metaobjects. As an introduction to this interconnected structure, this section presents a partial enumeration of the kinds of information associated with each kind of metaobject. More detailed information is presented later.
A class metaobject determines the structure and the default behavior of its instances. The following information is associated with class metaobjects:
STRING or NIL.See also Section 29.3, “Classes”
A slot definition metaobject contains information about the definition of a slot. There are two kinds of slot definition metaobjects:
DEFCLASS forms.Associated with each class metaobject is a list of direct slot definition metaobjects representing the slots defined directly in the class. Also associated with each class metaobject is a list of effective slot definition metaobjects representing the set of slots accessible in instances of that class.
The following information is associated with both direct and effective slot definitions metaobjects:
DEFCLASS form.DEFCLASS form. The
initialization form together with its lexical environment is available
as a function of no arguments which, when called, returns the result
of evaluating the initialization form in its lexical environment. This
is called the initfunction of the slot.
STRING or NIL.Certain other information is only associated with direct slot definition metaobjects. This information applies only to the direct definition of the slot in the class (it is not inherited).
DEFCLASS form are broken down
into their equivalent readers and writers in the direct slot
definition.Information, including inherited information, which applies to the definition of a slot in a particular class in which it is accessible is associated only with effective slot definition metaobjects.
See also Section 29.4, “Slot Definitions”
A generic function metaobject contains information about a generic function over and above the information associated with each of the generic function's methods.
LIST.
The “declarations” are available as a list of declaration specifiers.
There is a slight misnomer in the naming of functions and options in this document: Where the term “declaration” is used, actually a declaration specifier is meant.
STRING or NIL.See also Section 29.5, “Generic Functions”
A method metaobject
contains information about a specific METHOD.
LIST of of non-NIL atoms.LIST.
FUNCTION. This
function can be applied to arguments and a list of next methods using
APPLY or FUNCALL.STRING or NIL.See also Section 29.6, “Methods”
A specializer metaobject
represents the specializers of a METHOD.
class metaobjects are themselves specializer metaobjects. A special
kind of specializer metaobject is used for EQL specializers.
See also Section 29.8, “Specializers”
A method combination metaobject represents the information about the method combination being used by a generic function.
This document does not specify the structure of method combination metaobjects.
See also Section 29.9, “Method Combinations”
The inheritance structure of the specified metaobject classes is
shown in Table 29.1, “Direct Superclass Relationships Among The Specified Metaobject Classes”. The class of every class
shown is STANDARD-CLASS except for the classes T and FUNCTION,
which are instances of the class BUILT-IN-CLASS, and the classes
GENERIC-FUNCTION and STANDARD-GENERIC-FUNCTION, which are
instances of the class CLOS:FUNCALLABLE-STANDARD-CLASS.
Table 29.1. Direct Superclass Relationships Among The Specified Metaobject Classes
Each class with a “yes” in the “Abstract”
column is an abstract class and is not intended to
be instantiated. The results are undefined if an attempt is made to
make an instance of one of these classes with MAKE-INSTANCE.
Each class with a “yes” in the “Subclassable” column can be used as direct superclass for portable programs. It is not meaningful to subclass a class that has a “no” in this column.
The class METHOD is also subclassable: It
is possible to create subclasses of METHOD that do not inherit
from STANDARD-METHOD.
The class CLOS:FUNCALLABLE-STANDARD-OBJECT's class
precedence list contains FUNCTION before STANDARD-OBJECT, not
after STANDARD-OBJECT.
This is the most transparent way to realize the [ANSI CL standard] requirement
(see the [ANSI CL standard] section 4.2.2
“Type Relationships”)
that GENERIC-FUNCTION's class precedence list contains
FUNCTION before STANDARD-OBJECT.
The classes STANDARD-CLASS, CLOS:STANDARD-DIRECT-SLOT-DEFINITION, CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION,
STANDARD-METHOD, CLOS:STANDARD-READER-METHOD,
CLOS:STANDARD-WRITER-METHOD and STANDARD-GENERIC-FUNCTION are called
standard metaobject
classes.
For each kind of metaobject, this is the class the user interface
macros presented in the CLOS use by default. These are also the
classes on which user specializations are normally based.
The classes BUILT-IN-CLASS, CLOS:FUNCALLABLE-STANDARD-CLASS and
CLOS:FORWARD-REFERENCED-CLASS are special-purpose class metaobject classes.
Built-in classes are instances of the class BUILT-IN-CLASS.
The class CLOS:FUNCALLABLE-STANDARD-CLASS provides a special kind of
instances described in Section 29.10.2, “Funcallable Instances”.
When the definition of a class references another class which has not
yet been defined, an instance of CLOS:FORWARD-REFERENCED-CLASS is used as
a stand-in until the class is actually defined.
CLOS:FORWARD-REFERENCED-CLASS in CLISPThe class CLOS:FORWARD-REFERENCED-CLASS is implemented in a way
that fixes several flaws in the [AMOP] specification.
It is not a subclass of CLASS and CLOS:SPECIALIZER, just a
subclass of CLOS:METAOBJECT, because forward references to classes are
not classes and cannot be used as specializers of methods. An [AMOP]
compatibility mode is provided, however, if you set the variable
CUSTOM:*FORWARD-REFERENCED-CLASS-MISDESIGN*
to T.
In this mode, CLOS:FORWARD-REFERENCED-CLASS is formally a subclass of
CLASS and CLOS:SPECIALIZER, but the behaviour of
CLOS:FORWARD-REFERENCED-CLASS instances is the same.
The [AMOP] says that the first argument of CLOS:ENSURE-CLASS-USING-CLASS can
be a CLOS:FORWARD-REFERENCED-CLASS.
But from the description of CLOS:ENSURE-CLASS, it is clear that it can
only be a class returned by FIND-CLASS, and [ANSI CL standard] FIND-CLASS
cannot return a CLOS:FORWARD-REFERENCED-CLASS.
The [AMOP] says that CLOS:ENSURE-CLASS-USING-CLASS creates a
CLOS:FORWARD-REFERENCED-CLASS for not-yet-defined class symbols among the
direct-superclasses list. But this leads to many
CLOS:FORWARD-REFERENCED-CLASS with the same name (since they cannot be
stored and retrieved through FIND-CLASS), and since CHANGE-CLASS
preserves the EQ-ness, after the class is defined, we have many
class objects with the same name.
In the direct-superclasses list of non-finalized classes,
CLOS:FORWARD-REFERENCED-CLASS instances can occur, denoting classes that
have not yet been defined. When or after such a class gets defined,
the CLOS:FORWARD-REFERENCED-CLASS instance is replaced with the real
class. CLISP uses simple object replacement, not CHANGE-CLASS, in
this process.
The class STANDARD-OBJECT is the default direct
superclass of the class STANDARD-CLASS. When an instance
of the class STANDARD-CLASS is created, and no direct superclasses are
explicitly specified, it defaults to the class STANDARD-OBJECT. In
this way, any behavior associated with the class STANDARD-OBJECT
will be inherited, directly or indirectly, by all instances of the class
STANDARD-CLASS. A subclass of STANDARD-CLASS may have a different
class as its default direct superclass, but that class must be a
subclass of the class STANDARD-OBJECT.
The same is true for CLOS:FUNCALLABLE-STANDARD-CLASS and
CLOS:FUNCALLABLE-STANDARD-OBJECT.
The class CLOS:SPECIALIZER captures only the most basic behavior of
method specializers, and is not itself intended to be instantiated. The
class CLASS is a direct subclass of CLOS:SPECIALIZER reflecting the
property that classes by themselves can be used as method specializers.
The class CLOS:EQL-SPECIALIZER is used for EQL specializers.
The purpose of the Metaobject Protocol is to provide users with a powerful mechanism for extending and customizing the basic behavior of the CLOS. As an object-oriented description of the basic CLOS behavior, the Metaobject Protocol makes it possible to create these extensions by defining specialized subclasses of existing metaobject classes.
The Metaobject Protocol provides this capability without interfering with the implementor's ability to develop high-performance implementations. This balance between user extensibility and implementor freedom is mediated by placing explicit restrictions on each. Some of these restrictions are general---they apply to the entire class graph and the applicability of all methods. These are presented in this section.
The following additional terminology is used to present these restrictions:
i is interposed
between two other classes k1 and k2 if and only
if there is some path, following direct superclasses, from the class
k1 to the class k2 which includes i.x1 ... xn, are
defined in this specification as the classes k1 ... kn, but in
the implementation, one or more of the specializers
xl, is a superclass of the class
given in the specification kl.
For a given generic function and set of arguments, a
method k2 extends
a method k1 if and only if:
k1 and
k2 are both associated with the given generic function
k1 and k2 are both applicable to the given
arguments,k2 is executed
before k1,k1 will be executed if and only if
CALL-NEXT-METHOD is invoked from within the body of k2 and
CALL-NEXT-METHOD is invoked from within the body
of k2, thereby causing k1 to be executed.
For a given generic function and set of arguments, a
method k2 overrides
a method k1 if and only if conditions i
through iv above hold and,
instead of v,
CALL-NEXT-METHOD is not invoked from within the
body of k2, thereby preventing k1 from being executed.
Portable programs are allowed to define subclasses of specified classes, and are permitted to define methods on specified generic functions, with the following restrictions:
EQL specializer whose associated value is an instance of a specified
class.CALL-NEXT-METHOD.Portable programs may define methods that override specified methods only when the description of the specified method explicitly allows this. Typically, when a method is allowed to be overridden, a small number of related methods will need to be overridden as well.
An example of this is the specified methods on the generic
functions CLOS:ADD-DEPENDENT, CLOS:REMOVE-DEPENDENT and CLOS:MAP-DEPENDENTS.
Overriding a specified method on one of these generic functions requires
that the corresponding method on the other two generic functions be
overridden as well.
Portable methods on specified generic functions
specialized to portable metaobject classes must be defined before any
instances of those classes (or any subclasses) are created, either
directly or indirectly by a call to MAKE-INSTANCE. Methods can be
defined after instances are created by ALLOCATE-INSTANCE however.
Portable metaobject classes cannot be redefined.
The purpose of this last restriction is to permit implementations to provide performance optimizations by analyzing, at the time the first instance of a metaobject class is initialized, what portable methods will be applicable to it. This can make it possible to optimize calls to those specified generic functions which would have no applicable portable methods.
When a metaobject class is redefined,
CLISP issues a WARNING that the redefinition has no effect.
To avoid this warning, place all metaobject class definitions in a
separate file, compile it in a separate session
(because DEFCLASS in CLISP is evaluated at compile time too;
see Section 29.2.3.2, “Compile-file Processing of Specific User Interface Macros”),
and then LOAD it only once per session.
The results are undefined if any of these restrictions are violated.
The specification technology used in this document needs further development. The concepts of object-oriented protocols and subclass specialization are intuitively familiar to programmers of object-oriented systems; the protocols presented here fit quite naturally into this framework. Nonetheless, in preparing this document, we have found it difficult to give specification-quality descriptions of the protocols in a way that makes it clear what extensions users can and cannot write. Object-oriented protocol specification is inherently about specifying leeway, and this seems difficult using current technology.
Implementations are allowed latitude to modify the structure of specified classes and methods. This includes: the interposition of implementation-specific classes; the promotion of specified methods; and the consolidation of two or more specified methods into a single method specialized to interposed classes.
Any such modifications are permitted only so long as for any
portable class k that is a subclass of one or more specified classes
k1 ... kn, the following conditions are met:
k, the
classes k1 ... kn must appear in the same order as they would
have if no implementation-specific modifications had been made.
k may inherit, by virtue of
being a direct or indirect subclass of a specified class, any slot for
which the name is a symbol accessible in the “COMMON-LISP-USER” package or
exported by any package defined in the [ANSI CL standard].A list in which the first element is one of the symbols
DEFCLASS, DEFMETHOD, DEFGENERIC, DEFINE-METHOD-COMBINATION,
CLOS:GENERIC-FUNCTION, CLOS:GENERIC-FLET or CLOS:GENERIC-LABELS, and which has proper
syntax for that macro is called a user interface macro
form. This document provides an extended specification of
the DEFCLASS, DEFMETHOD and DEFGENERIC macros.
The user interface macros DEFCLASS, DEFGENERIC and DEFMETHOD
can be used not only to define metaobjects that are instances of the
corresponding standard metaobject class, but also to define metaobjects
that are instances of appropriate portable metaobject classes. To make
it possible for portable metaobject classes to properly process the
information appearing in the macro form, this document provides a
limited specification of the processing of these macro forms.
User interface macro forms can be evaluated or compiled and later executed. The effect of evaluating or executing a user interface macro form is specified in terms of calls to specified functions and generic functions which provide the actual behavior of the macro. The arguments received by these functions and generic functions are derived in a specified way from the macro form.
Converting a user interface macro form into the arguments to the appropriate functions and generic functions has two major aspects: the conversion of the macro argument syntax into a form more suitable for later processing, and the processing of macro arguments which are forms to be evaluated (including method bodies).
In the syntax of the DEFCLASS macro, the initform
and default-initarg-initial-value-form
arguments are forms which will be evaluated one or more times after the
macro form is evaluated or executed. Special processing must be done on
these arguments to ensure that the lexical scope of the forms is
captured properly. This is done by building a function of zero
arguments which, when called, returns the result of evaluating the form
in the proper lexical environment.
In the syntax of the DEFMETHOD macro
the forms argument is a list of forms that
comprise the body of the method definition. This list of forms must be
processed specially to capture the lexical scope of the macro form. In
addition, the lexical functions available only in the body of methods
must be introduced. To allow this and any other special processing
(such as slot access optimization), a specializable protocol is used for
processing the body of methods.
This is discussed in Section 29.6.3.1.1, “Processing Method Bodies”.
It is a common practice for Common Lisp compilers, while processing a file
or set of files, to maintain information about the definitions that have
been compiled so far. Among other things, this makes it possible to
ensure that a global macro definition (DEFMACRO form) which appears in
a file will affect uses of the macro later in that file.
This information about the state of the compilation is called the
COMPILE-FILE environment.
When compiling files containing CLOS definitions, it is useful
to maintain certain additional information in the COMPILE-FILE environment.
This can make it possible to issue various kinds of warnings (e.g.,
lambda list congruence) and to do various performance optimizations that
would not otherwise be possible.
At this time, there is such significant variance in the way
existing Common Lisp implementations handle COMPILE-FILE environments that it
would be premature to specify this mechanism. Consequently, this
document specifies only the behavior of evaluating or executing user
interface macro forms. What functions and generic functions are called
during COMPILE-FILE processing of a user interface macro form is not
specified. Implementations are free to define and document their own
behavior. Users may need to check implementation-specific behavior
before attempting to compile certain portable programs.
DEFCLASSSection 29.3.1, “Macro DEFCLASS”
CLISP evaluates DEFCLASS forms also at
compile time.
DEFMETHODSection 29.6.3.1, “Macro DEFMETHOD”
CLISP does not evaluate DEFMETHOD
forms at compile time except as necessary for signature checking.
DEFGENERICSection 29.5.3.1, “Macro DEFGENERIC”
CLISP does not evaluate DEFGENERIC
forms at compile time except as necessary for signature checking.
Like other objects, metaobjects can be created by calling
MAKE-INSTANCE. The initialization arguments passed to MAKE-INSTANCE
are used to initialize the metaobject in the usual way. The set of
legal initialization arguments, and their interpretation, depends on the
kind of metaobject being created. Implementations and portable programs
are free to extend the set of legal initialization arguments. Detailed
information about the initialization of each kind of metaobject are
provided in the appropriate sections:
DEFCLASSCLASS-NAMECLOS:CLASS-DIRECT-SUPERCLASSESCLOS:CLASS-DIRECT-SLOTSCLOS:CLASS-DIRECT-DEFAULT-INITARGSCLOS:CLASS-PRECEDENCE-LISTCLOS:CLASS-DIRECT-SUBCLASSESCLOS:CLASS-SLOTSCLOS:CLASS-DEFAULT-INITARGSCLOS:CLASS-FINALIZED-PCLOS:CLASS-PROTOTYPE(SETF CLASS-NAME)CLOS:ENSURE-CLASSCLOS:ENSURE-CLASS-USING-CLASSCLOS:FINALIZE-INHERITANCEMAKE-INSTANCEALLOCATE-INSTANCECLOS:VALIDATE-SUPERCLASSCLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGSCLOS:DIRECT-SLOT-DEFINITION-CLASSCLOS:COMPUTE-CLASS-PRECEDENCE-LISTCLOS:COMPUTE-SLOTSCLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITIONCLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGSCLOS:EFFECTIVE-SLOT-DEFINITION-CLASSCLOS:COMPUTE-DEFAULT-INITARGSDEFCLASSThe evaluation or execution of a DEFCLASS form results in a call
to the CLOS:ENSURE-CLASS function. The arguments received by CLOS:ENSURE-CLASS
are derived from the DEFCLASS form in a defined way. The exact
macro-expansion of the DEFCLASS form is not defined, only the
relationship between the arguments to the DEFCLASS macro and the
arguments received by the CLOS:ENSURE-CLASS function. Examples of typical
DEFCLASS forms and sample expansions are shown in the following two
examples:
A DEFCLASS form with
standard slot and class options and an expansion of it that would
result in the proper call to CLOS:ENSURE-CLASS.
(defclass plane (moving-object graphics-object)
((altitude :initform 0 :accessor plane-altitude)
(speed))
(:default-initargs :engine *jet*))
(ensure-class 'plane
':direct-superclasses '(moving-object graphics-object)
':direct-slots (list (list ':name 'altitude
':initform '0
':initfunction #'(lambda () 0)
':readers '(plane-altitude)
':writers '((setf plane-altitude)))
(list ':name 'speed))
':direct-default-initargs (list (list ':engine
'*jet*
#'(lambda () *jet*))))
A DEFCLASS form
with non-standard class and slot options, and an expansion of it which
results in the proper call to CLOS:ENSURE-CLASS. Note that the order of
the slot options has not affected the order of the properties in the
canonicalized slot specification, but has affected the order of the elements
in the lists which are the values of those properties.
(defclass sst (plane)
((mach mag-step 2
locator sst-mach
locator mach-location
:reader mach-speed
:reader mach))
(:metaclass faster-class)
(another-option foo bar))
(ensure-class 'sst
':direct-superclasses '(plane)
':direct-slots (list (list ':name 'mach
':readers '(mach-speed mach)
'mag-step '2
'locator '(sst-mach mach-location)))
':metaclass 'faster-class
'another-option '(foo bar))
name argument to DEFCLASS
becomes the value of the first argument to CLOS:ENSURE-CLASS. This is
the only positional argument accepted by CLOS:ENSURE-CLASS; all other
arguments are keyword arguments.:DIRECT-SUPERCLASSES argument to DEFCLASS
becomes the value of the :DIRECT-SUPERCLASSES keyword argument to
CLOS:ENSURE-CLASS.The :DIRECT-SLOTS argument to DEFCLASS becomes
the value of the :DIRECT-SLOTS keyword argument to CLOS:ENSURE-CLASS.
Special processing of this value is done to regularize the form of
each slot specification and to properly capture the lexical scope of
the initialization forms. This is done by converting each slot
specification to a property list called a
canonicalized slot specification.
The resulting list of canonicalized slot specifications is the value
of the :DIRECT-SLOTS keyword argument.
Canonicalized slot
specifications are later used as the keyword arguments to a generic
function which will, in turn, pass them to MAKE-INSTANCE for use as
a set of initialization arguments. Each canonicalized slot specification is
formed from the corresponding slot specification as follows:
:NAME
property. This property appears in every
canonicalized slot specification.:INITFORM slot option is present in
the slot specification, then both the :INITFORM and
:INITFUNCTION properties are present in the canonicalized slot specification.
The value of the :INITFORM property is the
initialization form. The value of the :INITFUNCTION property is
a function of zero arguments which, when called, returns the result
of evaluating the initialization form in its proper lexical environment.
:INITFORM slot option is not present in
the slot specification, then either the :INITFUNCTION property
will not appear, or its value will be false. In such cases, the
value of the :INITFORM property, or whether it appears, is
unspecified.:INITARGS property is a list
of the values of each :INITARG slot option. If there are no
:INITARG slot options, then either the :INITARGS property
will not appear or its value will be the empty list.
:READERS property is a list of
the values of each :READER and :ACCESSOR slot option. If
there are no :READER or :ACCESSOR slot options, then either
the :READERS property will not appear or its value will be the
empty list.:WRITERS property is a list of
the values specified by each :WRITER and :ACCESSOR slot
option. The value specified by a :WRITER slot option is just
the value of the slot option. The value specified by an
:ACCESSOR slot option is a two element list: the first element
is the symbol SETF, the second element is the value of the slot
option. If there are no :WRITER or :ACCESSOR slot options,
then either the :WRITERS property will not appear or its value
will be the empty list.:DOCUMENTATION property is the
value of the :DOCUMENTATION slot option. If there is no
:DOCUMENTATION slot option, then either the :DOCUMENTATION
property will not appear or its value will be false.
:ALLOCATION and :TYPE), but also any other options and
values appearing in the slot specification. If one of these slot
options appears more than once, the value of the property will be a
list of the specified values.The default initargs class
option, if it is present in the DEFCLASS form, becomes the value of
the :DIRECT-DEFAULT-INITARGS keyword argument to CLOS:ENSURE-CLASS.
Special processing of this value is done to properly capture the
lexical scope of the default value forms. This is done by converting
each default initarg in the class option into a
canonicalized default initialization argument.
The resulting list of canonicalized default initialization arguments is the value of
the :DIRECT-DEFAULT-INITARGS keyword argument to CLOS:ENSURE-CLASS.
A canonicalized default initarg is a list of three elements. The first element is the name; the second is the actual form itself; and the third is a function of zero arguments which, when called, returns the result of evaluating the default value form in its proper lexical environment.
If a default initargs
class option is not present in the DEFCLASS form,
:DIRECT-DEFAULT-INITARGS NIL is passed to CLOS:ENSURE-CLASS.
This is needed to
fulfill the [ANSI CL standard] requirement (see Section 4.6, “Redefining Classes ”) that
the resulting CLASS object reflects the DEFCLASS form.
The metaclass class
option, if it is present in the DEFCLASS form, becomes the value of
the :METACLASS keyword argument to CLOS:ENSURE-CLASS.
If a metaclass
class option is not present in the DEFCLASS form,
:METACLASS STANDARD-CLASS is passed to CLOS:ENSURE-CLASS.
This is needed to
fulfill the [ANSI CL standard] requirement (see Section 4.6, “Redefining Classes ”) that
the resulting CLASS object reflects the DEFCLASS form.
The documentation class
option, if it is present in the DEFCLASS form, becomes the value of
the :DOCUMENTATION keyword argument to CLOS:ENSURE-CLASS.
If a documentation
class option is not present in the DEFCLASS form,
:DIRECT-DEFAULT-INITARGS NIL is passed to CLOS:ENSURE-CLASS.
This is needed to
fulfill the [ANSI CL standard] requirement (see Section 4.6, “Redefining Classes ”) that
the resulting CLASS object reflects the DEFCLASS form.
Any other class options become the value of keyword
arguments with the same name. The value of the keyword argument is
the tail of the class option. An ERROR is SIGNALed if any class
option appears more than once in the DEFCLASS form.
The default initargs of the
metaclass are added at the end of the list
of arguments to pass to CLOS:ENSURE-CLASS.
This is needed to
fulfill the [ANSI CL standard] requirement (see Section 4.6, “Redefining Classes ”) that
the resulting CLASS object reflects the DEFCLASS form.
In the call to CLOS:ENSURE-CLASS, every element of its arguments
appears in the same left-to-right order as the corresponding element of
the DEFCLASS form, except that the order of the properties of
canonicalized slot specifications is unspecified. The values of
properties in canonicalized slot specifications do follow this ordering
requirement. Other ordering relationships in the keyword arguments to
CLOS:ENSURE-CLASS are unspecified.
The result of the call to CLOS:ENSURE-CLASS is returned as the result
of evaluating or executing the DEFCLASS form.
CLASS-NAMECLOS:CLASS-DIRECT-SUPERCLASSESCLOS:CLASS-DIRECT-SLOTSCLOS:CLASS-DIRECT-DEFAULT-INITARGSCLOS:CLASS-PRECEDENCE-LISTCLOS:CLASS-DIRECT-SUBCLASSESCLOS:CLASS-SLOTSCLOS:CLASS-DEFAULT-INITARGSCLOS:CLASS-FINALIZED-PCLOS:CLASS-PROTOTYPEIn this and the following sections, the “reader” generic functions which simply return information associated with a particular kind of metaobject are presented together. General information is presented first, followed by a description of the purpose of each, and ending with the specified methods for these generic functions.
The reader generic functions which simply return information associated with class metaobjects are presented together in this section.
Each of the reader generic functions for class metaobjects has the same
syntax, accepting one required argument called class, which must be
a class metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if
the class metaobject has not been initialized.
These generic functions can be called by the user or the implementation.
For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.
CLASS-NAME(CLASS-NAME class)Returns the name of class. This value can be any Lisp object,
but is usually a symbol, or NIL if the class has no name. This is the
defaulted value of the :NAME initialization argument that was
associated with the class during initialization or reinitialization.
(Also see (SETF CLASS-NAME).)
CLOS:CLASS-DIRECT-SUPERCLASSES(CLOS:CLASS-DIRECT-SUPERCLASSES class)Returns a list of the direct superclasses of class. The
elements of this list are class metaobjects. The empty list is returned if
class has no direct superclasses. This is the defaulted value of
the :DIRECT-SUPERCLASSES initialization argument that was associated
with the class during initialization or reinitialization.
For a class that has not yet been finalized,
the returned list may contain CLOS:FORWARD-REFERENCED-CLASS instances as
placeholder for classes that were not yet defined when finalization of
the class was last attempted.
CLOS:CLASS-DIRECT-SLOTS(CLOS:CLASS-DIRECT-SLOTS class)Returns a set of the direct slots of class. The elements of
this set are direct slot definition metaobjects. If the class has no direct slots, the empty set
is returned. This is the defaulted value of the :DIRECT-SLOTS
initialization argument that was associated with the class during
initialization and reinitialization.
CLOS:CLASS-DIRECT-DEFAULT-INITARGSReturns a list of the direct default initialization arguments for
class. Each element of this list is a canonicalized default initialization argument.
The empty list is returned if class has no
direct default initialization arguments. This is the defaulted value of
the :DIRECT-DEFAULT-INITARGS initialization argument that was
associated with the class during initialization or reinitialization.
CLOS:CLASS-PRECEDENCE-LIST(CLOS:CLASS-PRECEDENCE-LIST class)Returns the class precedence list of class.
The elements of this list are class metaobjects.
During class finalization CLOS:FINALIZE-INHERITANCE calls
CLOS:COMPUTE-CLASS-PRECEDENCE-LIST to compute the class precedence list of the class. That
value is associated with the class metaobject and is returned by CLOS:CLASS-PRECEDENCE-LIST.
This generic function SIGNALs an ERROR if class has not been finalized.
CLOS:CLASS-DIRECT-SUBCLASSES(CLOS:CLASS-DIRECT-SUBCLASSES class)Returns a set of the direct subclasses of class. The elements
of this set are class metaobjects that all mention this class among their direct
superclasses. The empty set is returned if class has no direct
subclasses. This value is maintained by the generic functions
CLOS:ADD-DIRECT-SUBCLASS and CLOS:REMOVE-DIRECT-SUBCLASS.
The set of direct subclasses of a class is
internally managed as a EXT:WEAK-LIST. Therefore the existence of
the CLOS:CLASS-DIRECT-SUBCLASSES function does not prevent otherwise
unreferenced classes from being garbage-collected.
CLOS:CLASS-SLOTS(CLOS:CLASS-SLOTS class)Returns a possibly empty set of the slots accessible in instances
of class. The elements of this set are effective slot definition metaobjects.
During class finalization CLOS:FINALIZE-INHERITANCE calls
CLOS:COMPUTE-SLOTS to compute the slots of the class. That value is
associated with the class metaobject and is returned by CLOS:CLASS-SLOTS.
This generic function SIGNALs an ERROR if class has not been finalized.
CLOS:CLASS-DEFAULT-INITARGS(CLOS:CLASS-DEFAULT-INITARGS class)Returns a list of the default initialization arguments for class.
Each element of this list is a canonicalized default initialization argument.
The empty list is returned if class has no
default initialization arguments.
During finalization CLOS:FINALIZE-INHERITANCE calls
CLOS:COMPUTE-DEFAULT-INITARGS to compute the default initialization
arguments for the class. That value is associated with the class metaobject and
is returned by CLOS:CLASS-DEFAULT-INITARGS.
This generic function SIGNALs an ERROR if class has not been
finalized.
CLOS:CLASS-FINALIZED-P(CLOS:CLASS-FINALIZED-P class)Returns true if class has been finalized. Returns false
otherwise. Also returns false if the class has not been initialized.
CLOS:CLASS-PROTOTYPE(CLOS:CLASS-PROTOTYPE class)Returns a prototype instance of class. Whether the instance
is initialized is not specified. The results are undefined if a
portable program modifies the binding of any slot of a prototype instance.
This generic function SIGNALs an ERROR if class has not been finalized.
This allows non-consing[3]
access to slots with allocation :CLASS:
(defclass counter () ((count :allocation :class :initform 0 :reader how-many))) (defmethod initialize-instance :after ((obj counter) &rest args) (incf (slot-value obj 'count))) (defclass counted-object (counter) ((name :initarg :name)))
Now one can find out how many COUNTED-OBJECTs
have been created by using
(HOW-MANY (:
CLOS:CLASS-PROTOTYPE (FIND-CLASS 'COUNTER)))
(MAKE-INSTANCE'counted-object :name 'foo) ⇒#<COUNTED-OBJECT #x203028C9>(HOW-MANY (CLOS:CLASS-PROTOTYPE(FIND-CLASS'counter))) ⇒1(MAKE-INSTANCE'counted-object :name 'bar) ⇒#<COUNTED-OBJECT #x20306CB1>(HOW-MANY (CLOS:CLASS-PROTOTYPE(FIND-CLASS'counter))) ⇒2
The specified methods for the class metaobject reader generic functions are presented below.
Each entry in the table indicates a method on one of the reader generic functions, specialized to a specified class. The number in each entry is a reference to the full description of the method. The full descriptions appear after the table.
Class Reader Methods
CLOS:FINALIZE-INHERITANCE
(STANDARD-CLASS) or
CLOS:FINALIZE-INHERITANCE
(CLOS:FUNCALLABLE-STANDARD-CLASS)SIGNALs an ERROR.CLOS:ADD-DIRECT-SUBCLASS(CLASS
CLASS) and CLOS:REMOVE-DIRECT-SUBCLASS
(CLASS CLASS).
This method can be overridden only if those methods are overridden as
well.Class finalization is the process of computing the information a class inherits from its superclasses and preparing to actually allocate instances of the class. The class finalization process includes computing the class's class precedence list, the full set of slots accessible in instances of the class and the full set of default initialization arguments for the class. These values are associated with the class metaobject and can be accessed by calling the appropriate reader. In addition, the class finalization process makes decisions about how instances of the class will be implemented.
To support forward-referenced superclasses, and to account for the
fact that not all classes are actually instantiated, class finalization
is not done as part of the initialization of the class metaobject. Instead,
finalization is done as a separate protocol, invoked by calling the
generic function CLOS:FINALIZE-INHERITANCE. The exact point at which
CLOS:FINALIZE-INHERITANCE is called depends on the class of the class metaobject; for
STANDARD-CLASS it is called sometime after all the classes
superclasses are defined, but no later than when the first instance of
the class is allocated (by ALLOCATE-INSTANCE).
The first step of class finalization is computing the class
precedence list. Doing this first allows subsequent steps to access the
class precedence list. This step is performed by calling the generic
function CLOS:COMPUTE-CLASS-PRECEDENCE-LIST. The value returned from this call is associated
with the class metaobject and can be accessed by calling the CLOS:CLASS-PRECEDENCE-LIST generic
function.
The second step is computing the full set of slots that will be
accessible in instances of the class. This step is performed by calling
the generic function CLOS:COMPUTE-SLOTS. The result of this call is a list
of effective slot definition metaobjects. This value is associated with the class metaobject and can
be accessed by calling the CLOS:CLASS-SLOTS generic function.
The behavior of CLOS:COMPUTE-SLOTS is itself layered, consisting of
calls to CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS and CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION.
The final step of class finalization is computing the full set of
initialization arguments for the class. This is done by calling the
generic function CLOS:COMPUTE-DEFAULT-INITARGS. The value returned by this
generic function is associated with the class metaobject and can be
accessed by calling CLOS:CLASS-DEFAULT-INITARGS.
If the class was previously finalized, CLOS:FINALIZE-INHERITANCE may
call MAKE-INSTANCES-OBSOLETE. The circumstances under which this
happens are described in the [ANSI CL standard] section
Section 4.6, “Redefining Classes ”.
Forward-referenced classes, which provide a temporary definition
for a class which has been referenced but not yet defined, can never be
finalized. An ERROR is SIGNALed if CLOS:FINALIZE-INHERITANCE is called on a
forward-referenced class.
A class metaobject can be created by calling MAKE-INSTANCE.
The initialization arguments establish the definition of the class.
A class metaobject can be redefined by calling REINITIALIZE-INSTANCE.
Some classes of class metaobject do not support redefinition;
in these cases, REINITIALIZE-INSTANCE SIGNALs an ERROR.
Initialization of a class metaobject must be done by calling MAKE-INSTANCE
and allowing it to call INITIALIZE-INSTANCE. Reinitialization of a
class metaobject must be done by calling REINITIALIZE-INSTANCE.
Portable programs must not
INITIALIZE-INSTANCE directly to
initialize a class metaobject;SHARED-INITIALIZE directly to
initialize or reinitialize a class metaobject;CHANGE-CLASS to change the class of any
class metaobject or to turn a non-class object into a
class metaobject.Since metaobject classes may not be redefined,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-REDEFINED-CLASS on class metaobjects.
Since the class of class metaobjects may not be changed,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on class metaobjects.
During initialization or reinitialization, each initialization argument is checked for errors and then associated with the class metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.2, “Initialization arguments and accessors for class metaobjects”.
This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. Initialization behavior specific to the different specified class metaobject classes comes next. The section ends with a set of restrictions on portable methods affecting class metaobject initialization and reinitialization.
In these descriptions, the phrase “this argument defaults to
value” means that when that initialization argument is not
supplied, initialization or reinitialization is performed as if
value had been supplied. For some initialization arguments this
could be done by the use of default initialization arguments, but
whether it is done this way is not specified. Implementations are free
to define default initialization arguments for specified class metaobject classes.
Portable programs are free to define default initialization arguments
for portable subclasses of the class CLASS.
Unless there is a specific note to the contrary, then during reinitialization, if an initialization argument is not supplied, the previously stored value is left unchanged.
The :DIRECT-DEFAULT-INITARGS argument is a list
of canonicalized default initialization arguments.
An ERROR is SIGNALed if this value is not a proper list, or if any
element of the list is not a canonicalized default initialization argument.
If the class metaobject is being initialized, this argument defaults to the empty list.
The :DIRECT-SLOTS argument is a list of
canonicalized slot specifications.
An ERROR is SIGNALed if this value is not a proper list or if any
element of the list is not a canonicalized slot specification.
After error checking, this value is converted to a
list of direct slot definition metaobjects before it is associated with the class metaobject. Conversion
of each canonicalized slot specification to a direct slot definition metaobject is a two-step process.
First, the generic function CLOS:DIRECT-SLOT-DEFINITION-CLASS is called with the class metaobject and
the canonicalized slot specification to determine the class of the new
direct slot definition metaobject; this permits both the class metaobject and the
canonicalized slot specification to control the resulting direct slot definition metaobject class.
Second, MAKE-INSTANCE is applied to the direct slot definition metaobject class and the
canonicalized slot specification.
This conversion could be implemented as shown in the
following code:
(DEFUNconvert-to-direct-slot-definition (class canonicalized-slot) (APPLY#'MAKE-INSTANCE(APPLY#'CLOS:DIRECT-SLOT-DEFINITION-CLASSclass canonicalized-slot) canonicalized-slot))
If the class metaobject is being initialized, this argument defaults to the empty list.
Once the direct slot definition metaobjects have been created, the specified reader and
writer methods are created. The generic functions
CLOS:READER-METHOD-CLASS and CLOS:WRITER-METHOD-CLASS are called to
determine the classes of the method metaobjects created.
The :DIRECT-SUPERCLASSES argument is a list of
class metaobjects. Classes which do not support multiple inheritance
signal an error if the list contains more than one element.
An ERROR is SIGNALed if this value is not a proper list or if
CLOS:VALIDATE-SUPERCLASS applied to class and any element of this
list returns false.
When the class metaobject is being initialized, and this argument is
either not supplied or is the empty list, this argument defaults as
follows: if the class is an instance of STANDARD-CLASS or one of
its subclasses the default value is a list of the class
STANDARD-OBJECT; if the class is an instance of
CLOS:FUNCALLABLE-STANDARD-CLASS or one of its subclasses the default
value is a list of the class
CLOS:FUNCALLABLE-STANDARD-OBJECT.
If the class is an instance of
STRUCTURE-CLASS or one of its subclasses the default value is a
list of the class STRUCTURE-OBJECT
After any defaulting of the value, the generic function
CLOS:ADD-DIRECT-SUBCLASS is called once for each element of the list.
When the class metaobject is being reinitialized and this
argument is supplied, the generic function CLOS:REMOVE-DIRECT-SUBCLASS
is called once for each class metaobject in the previously stored value but not
in the new value; the generic function CLOS:ADD-DIRECT-SUBCLASS is
called once for each class metaobject in the new value but not in the
previously stored value.
:DOCUMENTATION argument is
a STRING or NIL. An ERROR is SIGNALed if it is not. This argument default
to NIL during initialization.The :NAME argument is an object.
If the class is being initialized, this argument defaults to
NIL.
After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the class metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:
Table 29.2. Initialization arguments and accessors for class metaobjects
| Initialization Argument | Generic Function |
|---|---|
:DIRECT-DEFAULT-INITARGS | CLOS:CLASS-DIRECT-DEFAULT-INITARGS |
:DIRECT-SLOTS | CLOS:CLASS-DIRECT-SLOTS |
:DIRECT-SUPERCLASSES | CLOS:CLASS-DIRECT-SUPERCLASSES |
:DOCUMENTATION | DOCUMENTATION |
:NAME | CLASS-NAME |
Instances of the class STANDARD-CLASS support multiple
inheritance and reinitialization. Instances of the class
CLOS:FUNCALLABLE-STANDARD-CLASS support multiple inheritance and
reinitialization. For forward referenced classes, all of the
initialization arguments default to NIL.
Instances of the class STRUCTURE-CLASS do
not support multiple inheritance and reinitialization.
Since built-in classes cannot be created or reinitialized by the
user, an ERROR is SIGNALed if INITIALIZE-INSTANCE or REINITIALIZE-INSTANCE
are called to initialize or reinitialize a derived instance of the class
BUILT-IN-CLASS.
It is not specified which methods provide the initialization and reinitialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the class metaobject when either all or none of the specified initialization has taken effect.
These restrictions govern the methods that a portable program can
define on the generic functions INITIALIZE-INSTANCE,
REINITIALIZE-INSTANCE, and SHARED-INITIALIZE.
These restrictions apply only to methods on these generic functions for
which the first specializer is a subclass of the class CLASS.
Other portable methods on these generic functions are not affected by
these restrictions.
SHARED-INITIALIZE.For INITIALIZE-INSTANCE and REINITIALIZE-INSTANCE:
The results are undefined if any of these restrictions are violated.
class metaobjects created with MAKE-INSTANCE are usually anonymous
; that is, they have no proper name.
An anonymous class metaobject can be given a proper name using
( and
SETF FIND-CLASS)(.SETF CLASS-NAME)
When a class metaobject is created with MAKE-INSTANCE, it is initialized
in the usual way. The initialization arguments passed to
MAKE-INSTANCE are use to establish the definition of the class. Each
initialization argument is checked for errors and associated with the
class metaobject. The initialization arguments correspond roughly to the
arguments accepted by the DEFCLASS macro, and more closely to the
arguments accepted by the CLOS:ENSURE-CLASS function.
Some class metaobject classes allow their instances to be
redefined. When permissible, this is done by calling
REINITIALIZE-INSTANCE. This is discussed in the
next section.
An example of creating an anonymous class directly using
MAKE-INSTANCE follows:
(flet ((zero () 0)
(propellor () *propellor*))
(make-instance 'standard-class
:name '(my-class foo)
:direct-superclasses (list (find-class 'plane)
another-anonymous-class)
:direct-slots `((:name x
:initform 0
:initfunction ,#'zero
:initargs (:x)
:readers (position-x)
:writers ((setf position-x)))
(:name y
:initform 0
:initfunction ,#'zero
:initargs (:y)
:readers (position-y)
:writers ((setf position-y))))
:direct-default-initargs `((:engine *propellor* ,#'propellor))))
Some class metaobject classes allow their instances to be reinitialized.
This is done by calling REINITIALIZE-INSTANCE. The initialization
arguments have the same interpretation as in class initialization.
If the class metaobject was finalized before the call to REINITIALIZE-INSTANCE,
CLOS:FINALIZE-INHERITANCE will be called again once all the initialization
arguments have been processed and associated with the class metaobject.
In addition, once finalization is complete, any dependents of the
class metaobject will be updated by calling CLOS:UPDATE-DEPENDENT.
(SETF CLASS-NAME)CLOS:ENSURE-CLASSCLOS:ENSURE-CLASS-USING-CLASSCLOS:FINALIZE-INHERITANCEMAKE-INSTANCEALLOCATE-INSTANCECLOS:VALIDATE-SUPERCLASSCLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGSCLOS:DIRECT-SLOT-DEFINITION-CLASSCLOS:COMPUTE-CLASS-PRECEDENCE-LISTCLOS:COMPUTE-SLOTSCLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITIONCLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGSCLOS:EFFECTIVE-SLOT-DEFINITION-CLASSCLOS:COMPUTE-DEFAULT-INITARGS(SETF CLASS-NAME)((SETF CLASS-NAME) new-name
class)classnew-namenew-name argument.This function changes the name of class to new-name.
This value is usually a symbol, or NIL if the class has no name.
This function works by calling REINITIALIZE-INSTANCE with
class as its first argument, the symbol :NAME as its second
argument and new-name as its third argument.
CLOS:ENSURE-CLASS(CLOS:ENSURE-CLASS name &KEY
&ALLOW-OTHER-KEYS)nameSYMBOL.CLOS:ENSURE-CLASS-USING-CLASS,
others are processed during initialization of the class metaobject
(as described in Section 29.3.5.1, “Initialization of class metaobjects”).
This function is called to define or redefine a
class with the specified name, and can be called by the user or the
implementation. It is the functional equivalent of DEFCLASS, and
is called by the expansion of the DEFCLASS macro.
The behavior of this function is actually implemented by the
generic function CLOS:ENSURE-CLASS-USING-CLASS. When CLOS:ENSURE-CLASS is called,
it immediately calls CLOS:ENSURE-CLASS-USING-CLASS and returns that result as its
own.
The first argument to CLOS:ENSURE-CLASS-USING-CLASS is computed as
follows:
name names a class (FIND-CLASS returns a
class when called with name) use that class.NIL.
The second argument is name. The remaining arguments are the
complete set of keyword arguments received by the CLOS:ENSURE-CLASS
function.
CLOS:ENSURE-CLASS-USING-CLASS(CLOS:ENSURE-CLASS-USING-CLASS class name &KEY
:DIRECT-DEFAULT-INITARGS :DIRECT-SLOTS :DIRECT-SUPERCLASSES
:NAME :METACLASS &ALLOW-OTHER-KEYS)
classNIL.name:METACLASSSTANDARD-CLASS. If a class name is supplied, it is interpreted
as the class with that name. If a class name is supplied, but
there is no such class, an ERROR is SIGNALed.:DIRECT-SUPERCLASSESERROR is SIGNALed if this argument is not a
proper list.This generic function is called to define or modify
the definition of a named class. It is called by the CLOS:ENSURE-CLASS
function. It can also be called directly.
The first step performed by this generic function is to compute the set of initialization arguments which will be used to create or reinitialize the named class. The initialization arguments are computed from the full set of keyword arguments received by this generic function as follows:
:METACLASS argument is not included in the
initialization arguments.If the :DIRECT-SUPERCLASSES argument was received
by this generic function, it is converted into a list of class metaobjects.
This conversion does not affect the structure of the supplied
:DIRECT-SUPERCLASSES argument. For each element in the
:DIRECT-SUPERCLASSES argument:
Otherwise an instance of the class
CLOS:FORWARD-REFERENCED-CLASS is created and used.
The proper name of the newly created forward referenced
class metaobject is set to the element.
A new CLOS:FORWARD-REFERENCED-CLASS
instance is only created when one for the given class name
does not yet exist; otherwise the existing one is reused.
See Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP.
If the class argument is NIL, a new class metaobject is created
by calling the MAKE-INSTANCE generic function with the value of the
:METACLASS argument as its first argument, and the previously
computed initialization arguments. The proper name of the
newly created class metaobject is set to name. The newly created class metaobject is
returned.
If the class argument is a forward referenced class,
CHANGE-CLASS is called to change its class to the value specified
by the :METACLASS argument. The class metaobject is then reinitialized with
the previously initialization arguments. (This is a documented
violation of the general constraint that CHANGE-CLASS may not be
used with class metaobjects.)
The class argument cannot be a forward referenced class. See
Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP.
If the class of the class argument is not the same as the
class specified by the :METACLASS argument, an ERROR is SIGNALed.
Otherwise, the class metaobject class is redefined by calling the
REINITIALIZE-INSTANCE generic function with class and the
initialization arguments. The class argument is then
returned.
Methods
(CLOS:ENSURE-CLASS-USING-CLASS
(class CLASS) name &KEY :METACLASS
:DIRECT-SUPERCLASSES &ALLOW-OTHER-KEYS)This method implements the behavior of the generic
function in the case where the class argument is a class.
This method can be overridden.
(CLOS:ENSURE-CLASS-USING-CLASS
(class CLOS:FORWARD-REFERENCED-CLASS) name &KEY :METACLASS
:DIRECT-SUPERCLASSES &ALLOW-OTHER-KEYS)This method implements the behavior of the generic
function in the case where the class argument is a forward
referenced class.
This method does not exist.
See Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP.
Use the method specialized on NULL instead.
(CLOS:ENSURE-CLASS-USING-CLASS
(class NULL) name &KEY :METACLASS
:DIRECT-SUPERCLASSES &ALLOW-OTHER-KEYS)class argument is NIL.
CLOS:FINALIZE-INHERITANCE(CLOS:FINALIZE-INHERITANCE
class)classThis generic function is called to finalize a class metaobject. This is described in Section 29.3.4, “Class Finalization Protocol”
After CLOS:FINALIZE-INHERITANCE returns, the class metaobject is
finalized and the result of calling CLOS:CLASS-FINALIZED-P on the class metaobject
will be true.
Methods
(CLOS:FINALIZE-INHERITANCE
(class STANDARD-CLASS))(CLOS:FINALIZE-INHERITANCE
(class CLOS:FUNCALLABLE-STANDARD-CLASS))(CLOS:FINALIZE-INHERITANCE
(class CLOS:FORWARD-REFERENCED-CLASS))SIGNALs an ERROR.
MAKE-INSTANCE(MAKE-INSTANCE class &REST
initargs)classinitargsclass.
MAKE-INSTANCE creates and
returns a new instance of the given class. Its behavior and use is
described in the [ANSI CL standard].
Methods
(MAKE-INSTANCE
(class SYMBOL) &REST initargs)MAKE-INSTANCE
recursively on the arguments (FIND-CLASS
class) and initargs.(MAKE-INSTANCE (class
STANDARD-CLASS) &REST initargs)(MAKE-INSTANCE (class
CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)MAKE-INSTANCE described in the [ANSI CL standard] section
7.1
“Object Creation and Initialization”.
ALLOCATE-INSTANCE(ALLOCATE-INSTANCE class
&REST initargs)classinitargsclass
This generic function is called to create a new, uninitialized instance of a class. The interpretation of the concept of an uninitialized instance depends on the class metaobject class.
Before allocating the new instance, CLOS:CLASS-FINALIZED-P is
called to see if class has been finalized. If it has not been
finalized, CLOS:FINALIZE-INHERITANCE is called before the new instance
is allocated.
Methods
(ALLOCATE-INSTANCE
(class STANDARD-CLASS) &REST initargs:INSTANCE. These slots are unbound.
Slots with any other allocation are ignored by this method (no
ERROR is SIGNALed).(ALLOCATE-INSTANCE
(class CLOS:FUNCALLABLE-STANDARD-CLASS)
&REST initargs)This method allocates storage in the instance for
each slot with allocation :INSTANCE. These slots are unbound.
Slots with any other allocation are ignored by this method (no
ERROR is SIGNALed).
The funcallable instance function of the instance is
undefined - the results are undefined if the instance is applied to
arguments before CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION has been used
to set the funcallable instance function.
(ALLOCATE-INSTANCE
(class BUILT-IN-CLASS) &REST initargs)SIGNALs an ERROR.
CLOS:VALIDATE-SUPERCLASS(CLOS:VALIDATE-SUPERCLASS class
superclass)classsuperclassBOOLEAN.This generic function is called to determine whether
the class superclass is suitable for use as a superclass of
class.
This generic function can be be called by the implementation or user code. It is called during class metaobject initialization and reinitialization, before the direct superclasses are stored. If this generic function returns false, the initialization or reinitialization will signal an error.
Methods
(CLOS:VALIDATE-SUPERCLASS
(class CLASS) (superclass CLASS))This method returns true in three situations:
superclass argument is the class named T,
class argument is the same
as the class of the superclass argument, or
STANDARD-CLASS and the class of the other is
CLOS:FUNCALLABLE-STANDARD-CLASS.In all other cases, this method returns false.
This method can be overridden.
This method also returns true in a fourth situation:
class argument is a subclass
of the class of the superclass argument.
Remarks. Defining a method on CLOS:VALIDATE-SUPERCLASS requires detailed
knowledge of of the internal protocol followed by each of the two
class metaobject classes. A method on CLOS:VALIDATE-SUPERCLASS which returns true
for two different class metaobject classes declares that they are
compatible.
CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS(CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS class &REST
slot-spec)classslot-specThis generic function determines the initialization
arguments for the direct slot definition for a slot in a class.
It is called during initialization of a class. The resulting
initialization arguments are passed to CLOS:DIRECT-SLOT-DEFINITION-CLASS and then to
MAKE-INSTANCE.
This generic function uses the supplied canonicalized slot specification.
The value of :NAME in the returned initargs is the same as the value
of :NAME in the supplied slot-spec argument.
Methods
(CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS
(class STANDARD-CLASS) &REST slot-spec)(CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS (class
CLOS:FUNCALLABLE-STANDARD-CLASS) &REST slot-spec)This method returns slot-spec unmodified.
This method can be overridden.
CLOS:DIRECT-SLOT-DEFINITION-CLASS(CLOS:DIRECT-SLOT-DEFINITION-CLASS class &REST
initargs)classinitargsCLOS:DIRECT-SLOT-DEFINITION.
When a class is initialized, each of the canonicalized slot specifications must be converted to a direct slot definition metaobject. This generic function is called to determine the class of that direct slot definition metaobject.
The initargs argument is simply the
canonicalized slot specification for the slot.
Methods
(CLOS:DIRECT-SLOT-DEFINITION-CLASS
(class STANDARD-CLASS) &REST initargs)(CLOS:DIRECT-SLOT-DEFINITION-CLASS (class
CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)These methods return the class CLOS:STANDARD-DIRECT-SLOT-DEFINITION.
These methods can be overridden.
CLOS:COMPUTE-CLASS-PRECEDENCE-LIST(CLOS:COMPUTE-CLASS-PRECEDENCE-LIST
class)classThis generic-function is called to determine the class precedence list of a class.
The result is a list which contains each of class and its
superclasses once and only once. The first element of the list is
class and the last element is the class named T.
All methods on this generic function must compute the class
precedence list as a function of the ordered direct superclasses of
the superclasses of class. The results are undefined if the
rules used to compute the class precedence list depend on any other
factors.
When a class is finalized, CLOS:FINALIZE-INHERITANCE calls this
generic function and associates the returned value with the class metaobject.
The value can then be accessed by calling CLOS:CLASS-PRECEDENCE-LIST.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
Methods
(CLOS:COMPUTE-CLASS-PRECEDENCE-LIST (class
CLASS))This method computes the class precedence list according to the rules described in the [ANSI CL standard] section 4.3.5 “Determining the Class Precedence List”.
This method SIGNALs an ERROR if class or any of its superclasses
is a forward referenced class.
This method can be overridden.
CLOS:COMPUTE-SLOTS(CLOS:COMPUTE-SLOTS class)
classThis generic function computes a set of effective
slot definition metaobjects for the class class. The result is a list of effective slot definition metaobjects:
one for each slot that will be accessible in instances of class.
This generic function proceeds in 3 steps:
The first step collects the full set of direct slot
definitions from the superclasses of class.
The direct slot definitions are then collected into
individual lists, one list for each slot name associated with any of
the direct slot definitions. The slot names are compared with
EQL. Each such list is then sorted into class precedence list
order. Direct slot definitions coming from classes earlier in the
class precedence list of class appear before those coming from
classes later in the class precedence list. For each slot name, the
generic function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION is called to compute an effective slot
definition. The result of CLOS:COMPUTE-SLOTS is a list of these
effective slot definitions, in unspecified order.
In the final step, the location for each effective slot definition is set. This is done by specified around-methods; portable methods cannot take over this behavior. For more information on the slot definition locations, see Section 29.10.1, “Instance Structure Protocol”.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
Methods
(CLOS:COMPUTE-SLOTS
(class STANDARD-CLASS))(CLOS:COMPUTE-SLOTS
(class CLOS:FUNCALLABLE-STANDARD-CLASS)}These methods implement the specified behavior of the generic function.
These methods can be overridden.
(CLOS:COMPUTE-SLOTS
:AROUND (class STANDARD-CLASS))(CLOS:COMPUTE-SLOTS :AROUND
(class CLOS:FUNCALLABLE-STANDARD-CLASS))CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION class name direct-slot-definitions)
classnamedirect-slot-definitionsThis generic function determines the effective slot
definition for a slot in a class. It is called by CLOS:COMPUTE-SLOTS
once for each slot accessible in instances of class.
This generic function uses the supplied list of direct slot definition metaobjects to compute the inheritance of slot properties for a single slot. The returned effective slot definition represents the result of computing the inheritance. The name of the new effective slot definition is the same as the name of the direct slot definitions supplied.
The class of the effective slot definition metaobject is determined by calling
CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS. The effective slot definition is then created by
calling MAKE-INSTANCE. The initialization arguments passed in this
call to MAKE-INSTANCE are used to initialize the new effective slot definition metaobject.
See Section 29.4, “Slot Definitions” for details.
Methods
(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION (class
STANDARD-CLASS) name direct-slot-definitions)(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION (class
CLOS:FUNCALLABLE-STANDARD-CLASS) name direct-slot-definitions)This method implements the inheritance and defaulting of slot options following the rules described in the [ANSI CL standard] section 7.5.3 “Inheritance of Slots and Options”.
This method can be extended, but the value returned by the extending method must be the value returned by this method.
The initialization arguments that are passed
to CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS and MAKE-INSTANCE are computed through a call to
CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS. It is the CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS method that
implements the inheritance rules.
CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS class direct-slot-definitions)
classdirect-slot-definitionsThis generic function determines the initialization
arguments for the effective slot definition for a slot in a class.
It is called by CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION. The resulting initialization arguments
are passed to CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS and then to MAKE-INSTANCE.
This generic function uses the supplied list of direct slot definition metaobjects to
compute the inheritance of slot properties for a single slot. The
returned effective slot definition initargs represent the result of
computing the inheritance. The value of :NAME in the returned
initargs is the same as the name of the direct slot definitions
supplied.
Methods
(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS
(class STANDARD-CLASS) direct-slot-definitions)(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS (class
CLOS:FUNCALLABLE-STANDARD-CLASS) direct-slot-definitions)This method implements the inheritance and defaulting of slot options following the rules described in the [ANSI CL standard] section 7.5.3 “Inheritance of Slots and Options”.
This method can be extended.
CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS(CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS class &REST
initargs)classinitargsCLOS:EFFECTIVE-SLOT-DEFINITION-CLASS.
CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION to
determine the class of the resulting effective slot definition metaobject. The initargs
argument is the set of initialization arguments and values that will
be passed to MAKE-INSTANCE when the effective slot definition metaobject is created.
Methods
(CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS
(class STANDARD-CLASS) &REST initargs)(CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS (class
CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)These methods return the class CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION.
These methods can be overridden.
CLOS:COMPUTE-DEFAULT-INITARGS(CLOS:COMPUTE-DEFAULT-INITARGS
class)classThis generic-function is called to determine the default initialization arguments for a class.
The result is a list of canonicalized default initialization arguments, with no duplication among initialization argument names.
All methods on this generic function must compute the default initialization arguments as a function of only:
class,
andThe results are undefined if the rules used to compute the default initialization arguments depend on any other factors.
When a class is finalized, CLOS:FINALIZE-INHERITANCE calls this
generic function and associates the returned value with the class metaobject.
The value can then be accessed by calling
CLOS:CLASS-DEFAULT-INITARGS.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
Methods
(CLOS:COMPUTE-DEFAULT-INITARGS
(class STANDARD-CLASS))(CLOS:COMPUTE-DEFAULT-INITARGS
(class CLOS:FUNCALLABLE-STANDARD-CLASS))These methods compute the default initialization arguments according to the rules described in the [ANSI CL standard] section 7.1.3 “Defaulting of Initialization Arguments”.
These methods signal an error if class or any of its
superclasses is a forward referenced class.
These methods can be overridden.
CLOS:ADD-DIRECT-SUBCLASS(CLOS:ADD-DIRECT-SUBCLASS superclass
subclass)superclasssubclassThis generic function is called to maintain a set of
backpointers from a class to its direct subclasses. This generic
function adds subclass to the set of direct subclasses of
superclass.
When a class is initialized, this generic function is called once for each direct superclass of the class.
When a class is reinitialized, this generic function is
called once for each added direct superclass of the class. The
generic function CLOS:REMOVE-DIRECT-SUBCLASS is called once for each
deleted direct superclass of the class.
Methods
(CLOS:ADD-DIRECT-SUBCLASS
(superclass CLASS) (subclass CLASS))No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
CLOS:REMOVE-DIRECT-SUBCLASS(CLOS:REMOVE-DIRECT-SUBCLASS superclass
subclass)superclasssubclassThis generic function is called to maintain a set of
backpointers from a class to its direct subclasses. It removes
subclass from the set of direct subclasses of superclass. No
ERROR is SIGNALed if subclass is not in this set.
Whenever a class is reinitialized, this generic function is called once with each deleted direct superclass of the class.
Methods
(CLOS:REMOVE-DIRECT-SUBCLASS
(superclass CLASS) (subclass CLASS))No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
CLOS:SLOT-DEFINITION-NAMECLOS:SLOT-DEFINITION-ALLOCATIONCLOS:SLOT-DEFINITION-INITFORMCLOS:SLOT-DEFINITION-INITFUNCTIONCLOS:SLOT-DEFINITION-TYPECLOS:SLOT-DEFINITION-INITARGSCLOS:SLOT-DEFINITION-NAMECLOS:SLOT-DEFINITION-ALLOCATIONCLOS:SLOT-DEFINITION-INITFORMCLOS:SLOT-DEFINITION-INITFUNCTIONCLOS:SLOT-DEFINITION-TYPECLOS:SLOT-DEFINITION-INITARGSThe reader generic functions which simply return information associated with slot definition metaobjects are presented together here in the format described in Section 29.3.3, “Introspection: Readers for class metaobjects”.
Each of the reader generic functions for slot definition metaobjects has the same
syntax, accepting one required argument called slot, which must be a
slot definition metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if the slot definition metaobject
has not been initialized.
These generic functions can be called by the user or the implementation.
For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.
CLOS:SLOT-DEFINITION-NAMECLOS:SLOT-DEFINITION-ALLOCATIONCLOS:SLOT-DEFINITION-INITFORMCLOS:SLOT-DEFINITION-INITFUNCTIONCLOS:SLOT-DEFINITION-TYPECLOS:SLOT-DEFINITION-INITARGSCLOS:SLOT-DEFINITION-NAME(CLOS:SLOT-DEFINITION-NAME slot)Returns the name of slot. This value is a symbol that can be
used as a variable name. This is the value of the :NAME
initialization argument that was associated with the slot definition metaobject during
initialization.
CLOS:SLOT-DEFINITION-ALLOCATIONReturns the allocation of slot. This is a symbol. This is
the defaulted value of the :ALLOCATION initialization argument that
was associated with the slot definition metaobject during initialization.
CLOS:SLOT-DEFINITION-INITFORMReturns the initialization form of slot. This can be any
form. This is the defaulted value of the :INITFORM initialization
argument that was associated with the slot definition metaobject during initialization.
When slot has no initialization form, the value returned is
unspecified (however, CLOS:SLOT-DEFINITION-INITFUNCTION is guaranteed to return
NIL).
CLOS:SLOT-DEFINITION-INITFUNCTIONReturns the initialization function of slot. This value is
either a function of no arguments, or NIL, indicating that the slot
has no initialization function. This is the defaulted value of the
:INITFUNCTION initialization argument that was associated with the
slot definition metaobject during initialization.
CLOS:SLOT-DEFINITION-TYPE(CLOS:SLOT-DEFINITION-TYPE slot)Returns the type of slot. This is a type specifier name.
This is the defaulted value of the :TYPE initialization argument that
was associated with the slot definition metaobject during initialization.
CLOS:SLOT-DEFINITION-INITARGSReturns the set of initialization argument keywords for slot.
This is the defaulted value of the :INITARGS initialization argument
that was associated with the slot definition metaobject during initialization.
The specified methods for the slot definition metaobject readers
(CLOS:SLOT-DEFINITION-NAME
(slot-definition CLOS:STANDARD-SLOT-DEFINITION))(CLOS:SLOT-DEFINITION-ALLOCATION
(slot-definition CLOS:STANDARD-SLOT-DEFINITION))(CLOS:SLOT-DEFINITION-INITFORM
(slot-definition CLOS:STANDARD-SLOT-DEFINITION))(CLOS:SLOT-DEFINITION-INITFUNCTION
(slot-definition CLOS:STANDARD-SLOT-DEFINITION))(CLOS:SLOT-DEFINITION-TYPE
(slot-definition CLOS:STANDARD-SLOT-DEFINITION))(CLOS:SLOT-DEFINITION-INITARGS
(slot-definition CLOS:STANDARD-SLOT-DEFINITION))The following additional reader generic functions are defined for direct slot definition metaobjects.
CLOS:SLOT-DEFINITION-READERS(CLOS:SLOT-DEFINITION-READERS direct-slot-definition)Returns a (possibly empty) set of readers of the direct-slot-definition. This
value is a list of function names. This is the defaulted value of the
:READERS initialization argument that was associated with the direct
slot definition metaobject during initialization.
CLOS:SLOT-DEFINITION-WRITERS(CLOS:SLOT-DEFINITION-WRITERS direct-slot-definition)Returns a (possibly empty) set of writers of the direct-slot-definition. This
value is a list of function names. This is the defaulted value of the
:WRITERS initialization argument that was associated with the direct
slot definition metaobject during initialization.
(CLOS:SLOT-DEFINITION-READERS
(direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION))(CLOS:SLOT-DEFINITION-WRITERS
(direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION))
The following reader generic function is defined for effective slot definition metaobjects.
CLOS:SLOT-DEFINITION-LOCATION(CLOS:SLOT-DEFINITION-LOCATION effective-slot-definition)Returns the location of effective-slot-definition. The meaning and interpretation
of this value is described in Section 29.10.1, “Instance Structure Protocol”.
(CLOS:SLOT-DEFINITION-LOCATION
(effective-slot-definition CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))CLOS:COMPUTE-SLOTS :AROUND
(STANDARD-CLASS) and
CLOS:COMPUTE-SLOTS :AROUND
(CLOS:FUNCALLABLE-STANDARD-CLASS).
A slot definition metaobject can be created by calling MAKE-INSTANCE. The
initialization arguments establish the definition of the slot
definition. A slot definition metaobject cannot be redefined; calling
REINITIALIZE-INSTANCE SIGNALs an ERROR.
Initialization of a slot definition metaobject must be done by calling MAKE-INSTANCE
and allowing it to call INITIALIZE-INSTANCE.
Portable programs must not...
INITIALIZE-INSTANCE directly to
initialize a slot definition metaobject;SHARED-INITIALIZE directly to
initialize a slot definition metaobject;CHANGE-CLASS to change the class of any
slot definition metaobject or to turn a non-slot-definition object into a
slot definition metaobject.Since metaobject classes may not be redefined, no behavior is
specified for the result of calls to
UPDATE-INSTANCE-FOR-REDEFINED-CLASS on slot definition metaobjects. Since the class of a
slot definition metaobject cannot be changed, no behavior is specified for the result of
calls to UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on slot definition metaobjects.
During initialization, each initialization argument is checked for errors and then associated with the slot definition metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.3, “Initialization arguments and accessors for slot definition metaobjects”.
This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments.
In these descriptions, the phrase “this argument defaults to
value” means that when that initialization argument is not
supplied, initialization is performed as if value had been supplied.
For some initialization arguments this could be done by the use of
default initialization arguments, but whether it is done this way is not
specified. Implementations are free to define default initialization
arguments for specified slot definition metaobject classes. Portable programs are free to
define default initialization arguments for portable subclasses of the
class CLOS:SLOT-DEFINITION.
The :NAME argument is a slot name. An ERROR is SIGNALed
if this argument is not a symbol which can be used as a variable
name. An ERROR is SIGNALed if this argument is not supplied.
:INITFORM argument is a form. The
:INITFORM argument defaults to NIL. An ERROR is SIGNALed if the
:INITFORM argument is supplied, but the :INITFUNCTION argument
is not supplied.:INITFUNCTION argument is a function of zero
arguments which, when called, evaluates the :INITFORM in the
appropriate lexical environment. The :INITFUNCTION argument
defaults to false. An ERROR is SIGNALed if the :INITFUNCTION argument is
supplied, but the :INITFORM argument is not supplied.:TYPE argument is a type specifier name. An
ERROR is SIGNALed otherwise. The :TYPE argument defaults to the symbol T.
:ALLOCATION argument is a SYMBOL. An
ERROR is SIGNALed otherwise. The :ALLOCATION argument defaults to the
symbol :INSTANCE.:INITARGS argument is a LIST of SYMBOLs.
An ERROR is SIGNALed if this argument is not a proper list, or if any
element of this list is not a SYMBOL. The :INITARGS argument
defaults to the empty list.:READERS and :WRITERS arguments are
LISTs of function names. An ERROR is SIGNALed if they are not
proper lists, or if any element is not a valid function name.
They default to the empty list. An ERROR is SIGNALed if either of these
arguments is supplied and the metaobject is not a CLOS:DIRECT-SLOT-DEFINITION.
:DOCUMENTATION argument is
a STRING or NIL. An ERROR is SIGNALed if it is not. This argument default
to NIL during initialization.After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the slot definition metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:
Table 29.3. Initialization arguments and accessors for slot definition metaobjects
| Initialization Argument | Generic Function |
|---|---|
:NAME | CLOS:SLOT-DEFINITION-NAME |
:INITFORM | CLOS:SLOT-DEFINITION-INITFORM |
:INITFUNCTION | CLOS:SLOT-DEFINITION-INITFUNCTION |
:TYPE | CLOS:SLOT-DEFINITION-TYPE |
:ALLOCATION | CLOS:SLOT-DEFINITION-ALLOCATION |
:INITARGS | CLOS:SLOT-DEFINITION-INITARGS |
:READERS | CLOS:SLOT-DEFINITION-READERS |
:WRITERS | CLOS:SLOT-DEFINITION-WRITERS |
:DOCUMENTATION | DOCUMENTATION |
It is not specified which methods provide the initialization and reinitialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the slot definition metaobject when either all or none of the specified initialization has taken effect.
These restrictions govern the methods that a portable program can
define on the generic functions INITIALIZE-INSTANCE,
REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions
apply only to methods on these generic functions for which the first
specializer is a subclass of the class CLOS:SLOT-DEFINITION. Other portable
methods on these generic functions are not affected by these
restrictions.
SHARED-INITIALIZE or REINITIALIZE-INSTANCE.For INITIALIZE-INSTANCE:
The results are undefined if any of these restrictions are violated.
CLOS:GENERIC-FUNCTION-NAMECLOS:GENERIC-FUNCTION-METHODSCLOS:GENERIC-FUNCTION-LAMBDA-LISTCLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDERCLOS:GENERIC-FUNCTION-DECLARATIONSCLOS:GENERIC-FUNCTION-METHOD-CLASSCLOS:GENERIC-FUNCTION-METHOD-COMBINATION(SETF CLOS:GENERIC-FUNCTION-NAME)ENSURE-GENERIC-FUNCTIONCLOS:ENSURE-GENERIC-FUNCTION-USING-CLASSADD-METHODREMOVE-METHODCLOS:COMPUTE-APPLICABLE-METHODSCLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSESCLOS:COMPUTE-EFFECTIVE-METHODCLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTIONCLOS:MAKE-METHOD-LAMBDACLOS:COMPUTE-DISCRIMINATING-FUNCTIONCLOS:GENERIC-FUNCTION-NAMECLOS:GENERIC-FUNCTION-METHODSCLOS:GENERIC-FUNCTION-LAMBDA-LISTCLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDERCLOS:GENERIC-FUNCTION-DECLARATIONSCLOS:GENERIC-FUNCTION-METHOD-CLASSCLOS:GENERIC-FUNCTION-METHOD-COMBINATIONThe reader generic functions which simply return information associated with generic function metaobjects are presented together here in the format described in Section 29.3.3, “Introspection: Readers for class metaobjects”.
Each of the reader generic functions for generic function metaobjects has the same
syntax, accepting one required argument called generic-function, which must be a
generic function metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if the
generic function metaobject has not been initialized.
These generic functions can be called by the user or the implementation.
For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.
CLOS:GENERIC-FUNCTION-NAME(CLOS:GENERIC-FUNCTION-NAME generic-function)Returns the name of the generic function, or NIL if the generic
function has no name. This is the defaulted value of the :NAME
initialization argument that was associated with the generic function metaobject during
initialization or reinitialization.
(See also (SETF CLOS:GENERIC-FUNCTION-NAME).)
CLOS:GENERIC-FUNCTION-METHODS(CLOS:GENERIC-FUNCTION-METHODS generic-function)Returns the set of methods currently connected to the generic
function. This is a set of method metaobjects. This value is maintained by the
generic functions ADD-METHOD and REMOVE-METHOD.
CLOS:GENERIC-FUNCTION-LAMBDA-LIST(CLOS:GENERIC-FUNCTION-LAMBDA-LIST generic-function)Returns the lambda list of the generic function. This is the
defaulted value of the :LAMBDA-LIST initialization argument that was
associated with the generic function metaobject during initialization or reinitialization.
An ERROR is SIGNALed if the lambda list has yet to be supplied.
CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER(CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER generic-function)Returns the argument precedence order of the generic function.
This value is a list of symbols, a permutation of the required
parameters in the lambda list of the generic function. This is the
defaulted value of the :ARGUMENT-PRECEDENCE-ORDER initialization
argument that was associated with the generic function metaobject during initialization or
reinitialization.
An ERROR is SIGNALed if the lambda list has not yet been
supplied.
CLOS:GENERIC-FUNCTION-DECLARATIONS(CLOS:GENERIC-FUNCTION-DECLARATIONS generic-function)Returns a possibly empty list of the “declarations”
of the generic function. The elements of this list are
declaration specifiers. This list is the defaulted value of the
:DECLARATIONS initialization argument that was associated with the
generic function metaobject during initialization or reinitialization.
CLOS:GENERIC-FUNCTION-METHOD-CLASS(CLOS:GENERIC-FUNCTION-METHOD-CLASS generic-function)Returns the default method class of the generic function. This
class must be a subclass of the class METHOD. This is the defaulted
value of the :METHOD-CLASS initialization argument that was
associated with the generic function metaobject during initialization or reinitialization.
CLOS:GENERIC-FUNCTION-METHOD-COMBINATION(CLOS:GENERIC-FUNCTION-METHOD-COMBINATION generic-function)Returns the method combination of the generic function. This is a
method combination metaobject. This is the defaulted value of the :METHOD-COMBINATION
initialization argument that was associated with the generic function metaobject during
initialization or reinitialization.
The specified methods for the generic function metaobject reader generic functions
(CLOS:GENERIC-FUNCTION-NAME
(generic-function STANDARD-GENERIC-FUNCTION))(CLOS:GENERIC-FUNCTION-LAMBDA-LIST
(generic-function STANDARD-GENERIC-FUNCTION))(CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER
(generic-function STANDARD-GENERIC-FUNCTION))(CLOS:GENERIC-FUNCTION-DECLARATIONS
(generic-function STANDARD-GENERIC-FUNCTION))(CLOS:GENERIC-FUNCTION-METHOD-CLASS
(generic-function STANDARD-GENERIC-FUNCTION))(CLOS:GENERIC-FUNCTION-METHOD-COMBINATION
(generic-function STANDARD-GENERIC-FUNCTION))(CLOS:GENERIC-FUNCTION-METHODS
(generic-function STANDARD-GENERIC-FUNCTION))No behavior is specified for this method beyond that which is specified for the generic function.
The value returned by this method is maintained by
and
ADD-METHOD(STANDARD-GENERIC-FUNCTION
STANDARD-METHOD).REMOVE-METHOD(STANDARD-GENERIC-FUNCTION
STANDARD-METHOD)
DEFGENERICThe evaluation or execution of a DEFGENERIC form results in a
call to the ENSURE-GENERIC-FUNCTION function. The arguments received by ENSURE-GENERIC-FUNCTION
are derived from the DEFGENERIC form in a defined way. As with
DEFCLASS and DEFMETHOD, the exact macro-expansion of the
DEFGENERIC form is not defined, only the relationship between the
arguments to the macro and the arguments received by ENSURE-GENERIC-FUNCTION.
function-name
argument to DEFGENERIC becomes the first argument to ENSURE-GENERIC-FUNCTION.
This is the only positional argument accepted by ENSURE-GENERIC-FUNCTION; all other
arguments are keyword arguments.lambda-list argument to DEFGENERIC becomes the value
of the :LAMBDA-LIST keyword argument to ENSURE-GENERIC-FUNCTION.For each of the options :ARGUMENT-PRECEDENCE-ORDER,
:DOCUMENTATION, :GENERIC-FUNCTION-CLASS and :METHOD-CLASS, the value of the
option becomes the value of the keyword argument with the same name.
If the option does not appear in the macro form, the keyword argument
does not appear in the resulting call to ENSURE-GENERIC-FUNCTION.
If the option does not appear in the macro form,
the keyword argument appears in the resulting call to ENSURE-GENERIC-FUNCTION, with a
default value: the lambda-list for :ARGUMENT-PRECEDENCE-ORDER, NIL for
:DOCUMENTATION, the class STANDARD-GENERIC-FUNCTION for :GENERIC-FUNCTION-CLASS,
the class STANDARD-METHOD for :METHOD-CLASS.
This is needed to make the generic function reflect the DEFGENERIC form.
For the option :DECLARE, the list
of “declarations” becomes the value of the :DECLARATIONS
keyword argument. If the :DECLARE option does not
appear in the macro form, the :DECLARATIONS keyword argument does not
appear in the call to ENSURE-GENERIC-FUNCTION.
If the :DECLARE option does not appear in
the macro form, the :DECLARATIONS keyword argument appears in the
resulting call to ENSURE-GENERIC-FUNCTION, with a default value of NIL. This is
needed to make the generic function reflect the DEFGENERIC form.
The handling of the :METHOD-COMBINATION option is
not specified.
If the :METHOD-COMBINATION option does not
appear in the macro form, the :METHOD-COMBINATION keyword argument
still appears in the resulting call to ENSURE-GENERIC-FUNCTION, but in a position
where it can be overridden by user-defined initargs and default initargs.
The :DECLARE keyword is
recognized as equivalent to the :DECLARATIONS keyword, for
compatibility with ENSURE-GENERIC-FUNCTION in [ANSI CL standard]. If both :DECLARE and
:DECLARATIONS keyword arguments are specified, an ERROR is SIGNALed.
Any other generic function options become the value of
keyword arguments with the same name. The value of the keyword
argument is the tail of the generic function option. An ERROR is SIGNALed if
any generic function option appears more than once in the
DEFGENERIC form.
The default initargs of the
generic-function-class are added at the
end of the list of arguments to pass to ENSURE-GENERIC-FUNCTION. This is needed to
make the generic function reflect the DEFGENERIC form.
User-defined options. Any other options become the value of keyword arguments with
the same name. The value of the keyword argument is the tail of the
option. An ERROR is SIGNALed if any option appears more than once in the
DEFGENERIC form.
The result of the call to ENSURE-GENERIC-FUNCTION is returned as the result of
evaluating or executing the DEFGENERIC form.
Associated with each generic function is its discriminating function. Each time the generic function is called, the discriminating function is called to provide the behavior of the generic function. The discriminating function receives the full set of arguments received by the generic function. It must lookup and execute the appropriate methods, and return the appropriate values.
The discriminating function is computed by the highest layer of
the generic function invocation protocol, CLOS:COMPUTE-DISCRIMINATING-FUNCTION.
Whenever a generic function metaobject is initialized, reinitialized, or a method is added or
removed, the discriminating function is recomputed.
The new discriminating function is then stored with
CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION.
Discriminating functions call CLOS:COMPUTE-APPLICABLE-METHODS
and CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES to compute the methods
applicable to the generic functions arguments.
Applicable methods are combined by CLOS:COMPUTE-EFFECTIVE-METHOD to
produce an effective method
.
Provisions are made to allow memoization of the method applicability and
effective methods computations. (See the description of
CLOS:COMPUTE-DISCRIMINATING-FUNCTION for details.)
The body of method definitions are processed by CLOS:MAKE-METHOD-LAMBDA.
The result of this generic function is a lambda expression
which is processed by either COMPILE or COMPILE-FILE to produce a
method function.
The arguments received by the method function are controlled by the
CALL-METHOD forms appearing in the effective methods.
By default, method functions accept two arguments: a list of arguments
to the generic function, and a list of next methods.
The list of next methods corresponds to the next methods argument to
CALL-METHOD.
If CALL-METHOD appears with additional arguments, these will be passed
to the method functions as well; in these cases, CLOS:MAKE-METHOD-LAMBDA
must have created the method lambdas to expect additional arguments.
See The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented.
A generic function metaobject can be created by calling MAKE-INSTANCE. The
initialization arguments establish the definition of the generic
function. A generic function metaobject can be redefined by calling REINITIALIZE-INSTANCE.
Some classes of generic function metaobject do not support redefinition; in these cases,
REINITIALIZE-INSTANCE SIGNALs an ERROR.
Initialization of a generic function metaobject must be done by calling MAKE-INSTANCE
and allowing it to call INITIALIZE-INSTANCE. Reinitialization of a
generic function metaobject must be done by calling REINITIALIZE-INSTANCE.
Portable programs must not
INITIALIZE-INSTANCE directly to
initialize a generic function metaobject;SHARED-INITIALIZE directly to
initialize or reinitialize a generic function metaobject;CHANGE-CLASS to change the class of any
generic function metaobject or to turn a non-generic-function object into a
generic function metaobject.Since metaobject classes may not be redefined,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-REDEFINED-CLASS on generic function metaobjects.
Since the class of a generic function metaobject may not be changed,
no behavior is specified for the results of calls to
UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on generic function metaobjects.
During initialization or reinitialization, each initialization argument is checked for errors and then associated with the generic function metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.4, “Initialization arguments and accessors for generic function metaobjects”.
This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. The section ends with a set of restrictions on portable methods affecting generic function metaobject initialization and reinitialization.
In these descriptions, the phrase “this argument defaults to
value” means that when that initialization argument is not
supplied, initialization or reinitialization is performed as if
value had been supplied. For some initialization arguments this
could be done by the use of default initialization arguments, but
whether it is done this way is not specified. Implementations are free
to define default initialization arguments for specified generic function metaobject classes.
Portable programs are free to define default initialization arguments
for portable subclasses of the class GENERIC-FUNCTION.
Unless there is a specific note to the contrary, then during reinitialization, if an initialization argument is not supplied, the previously stored value is left unchanged.
The :ARGUMENT-PRECEDENCE-ORDER argument is a list
of symbols.
An ERROR is SIGNALed if this argument appears but the :LAMBDA-LIST
argument does not appear. An ERROR is SIGNALed if this value is not a
proper list or if this value is not a permutation of the
symbols from the required arguments part of the :LAMBDA-LIST
initialization argument.
When the generic function is being initialized or
reinitialized, and this argument is not supplied, but the
:LAMBDA-LIST argument is supplied, this value defaults to the
symbols from the required arguments part of the :LAMBDA-LIST
argument, in the order they appear in that argument. If neither
argument is supplied, neither are initialized (see the description of
:LAMBDA-LIST.)
The :DECLARATIONS argument is a list of declaration specifiers.
An ERROR is SIGNALed if this value is not a proper list or
if each of its elements is not a legal declaration specifier.
When the generic function is being initialized, and this argument is not supplied, it defaults to the empty list.
:DOCUMENTATION argument is
a STRING or NIL. An ERROR is SIGNALed if it is not. This argument default
to NIL during initialization.The :LAMBDA-LIST argument is a lambda list.
An ERROR is SIGNALed if this value is not a proper generic function
lambda list.
When the generic function is being initialized, and this argument is not supplied, the generic function's lambda list is not initialized. The lambda list will be initialized later, either when the first method is added to the generic function, or a later reinitialization of the generic function.
:METHOD-COMBINATION argument is a method combination metaobject.
The :METHOD-CLASS argument is a class metaobject.
An ERROR is SIGNALed if this value is not a subclass of the
class METHOD.
When the generic function is being initialized, and this
argument is not supplied, it defaults to the class STANDARD-METHOD.
The :NAME argument is an object.
If the generic function is being initialized, this argument
defaults to NIL.
After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the generic function metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:
Table 29.4. Initialization arguments and accessors for generic function metaobjects
| Initialization Argument | Generic Function |
|---|---|
:ARGUMENT-PRECEDENCE-ORDER | CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER |
:DECLARATIONS | CLOS:GENERIC-FUNCTION-DECLARATIONS |
:DOCUMENTATION | DOCUMENTATION |
:LAMBDA-LIST | CLOS:GENERIC-FUNCTION-LAMBDA-LIST |
:METHOD-COMBINATION | CLOS:GENERIC-FUNCTION-METHOD-COMBINATION |
:METHOD-CLASS | CLOS:GENERIC-FUNCTION-METHOD-CLASS |
:NAME | CLOS:GENERIC-FUNCTION-NAME |
It is not specified which methods provide the initialization and reinitialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the generic function metaobject when either all or none of the specified initialization has taken effect.
These restrictions govern the methods that a portable program can
define on the generic functions INITIALIZE-INSTANCE,
REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions
apply only to methods on these generic functions for which the first
specializer is a subclass of the class GENERIC-FUNCTION. Other
portable methods on these generic functions are not affected by these
restrictions.
SHARED-INITIALIZE.For INITIALIZE-INSTANCE and REINITIALIZE-INSTANCE:
The results are undefined if any of these restrictions are violated.
(SETF CLOS:GENERIC-FUNCTION-NAME)ENSURE-GENERIC-FUNCTIONCLOS:ENSURE-GENERIC-FUNCTION-USING-CLASSADD-METHODREMOVE-METHODCLOS:COMPUTE-APPLICABLE-METHODSCLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSESCLOS:COMPUTE-EFFECTIVE-METHODCLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTIONCLOS:MAKE-METHOD-LAMBDACLOS:COMPUTE-DISCRIMINATING-FUNCTION(SETF CLOS:GENERIC-FUNCTION-NAME)((SETF CLOS:GENERIC-FUNCTION-NAME) new-name generic-function)
generic-functionnew-nameNIL.
new-name argument.This function changes the name of generic-function to new-name.
This value is usually a function name or NIL, if the generic function
is to have no name.
This function works by calling REINITIALIZE-INSTANCE with
generic-function as its first argument, the symbol :NAME as its second argument
and new-name as its third argument.
ENSURE-GENERIC-FUNCTION(ENSURE-GENERIC-FUNCTION function-name &KEY
&ALLOW-OTHER-KEYS)function-nameCLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS, others are
processed during initialization of the generic function metaobject
(as described in Section 29.5.3.3, “Initialization of generic function metaobjects”).
This function is called to define a globally named generic function or to specify or modify options and declarations that pertain to a globally named generic function as a whole. It can be called by the user or the implementation.
It is the functional equivalent of DEFGENERIC, and is
called by the expansion of the DEFGENERIC and DEFMETHOD macros.
The behavior of this function is actually
implemented by the generic function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS. When ENSURE-GENERIC-FUNCTION
is called, it immediately calls CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS and returns that
result as its own.
The first argument to CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS is computed as follows:
function-name names a non-generic
function, a macro, or a special form, an ERROR is SIGNALed.
function-name names a generic function, that
generic function metaobject is used.NIL is used.
The second argument is function-name. The remaining arguments
are the complete set of keyword arguments received by ENSURE-GENERIC-FUNCTION.
CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS(CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS generic-function function-name &KEY
:ARGUMENT-PRECEDENCE-ORDER :DECLARATIONS :DOCUMENTATION
:GENERIC-FUNCTION-CLASS :LAMBDA-LIST :METHOD-CLASS :METHOD-COMBINATION
:NAME &ALLOW-OTHER-KEYS)generic-functionNIL.function-name:GENERIC-FUNCTION-CLASSSTANDARD-GENERIC-FUNCTION. If a class name is supplied, it is
interpreted as the class with that name. If a class name is
supplied, but there is no such class, an ERROR is SIGNALed.
see Section 29.5.3.3, “Initialization of generic function metaobjects”.
The :DECLARE keyword is recognized as
equivalent to the :DECLARATIONS keyword, for compatibility
with ENSURE-GENERIC-FUNCTION in [ANSI CL standard].
The generic function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS is called to
define or modify the definition of a globally named generic function.
It is called by the ENSURE-GENERIC-FUNCTION function. It can also be called
directly.
The first step performed by this generic function is to compute the set of initialization arguments which will be used to create or reinitialize the globally named generic function. These initialization arguments are computed from the full set of keyword arguments received by this generic function as follows:
:GENERIC-FUNCTION-CLASS
argument is not included in the initialization arguments.
:METHOD-CLASS argument was received by
this generic function, it is converted into a class metaobject.
This is done by looking up the class name with FIND-CLASS. If
there is no such class, an ERROR is SIGNALed.If the generic-function argument is NIL, an instance of the class
specified by the :GENERIC-FUNCTION-CLASS argument is created by
calling MAKE-INSTANCE with the previously computed initialization
arguments. The function name function-name is set to name the generic
function. The newly created generic function metaobject is returned.
If the class of the generic-function argument is not the same
as the class specified by the :GENERIC-FUNCTION-CLASS argument, an ERROR is SIGNALed.
The description of ENSURE-GENERIC-FUNCTION in [ANSI CL standard]
specifies that in this case, CHANGE-CLASS is called if the class of the
generic-function argument and the class specified by the :GENERIC-FUNCTION-CLASS argument are
compatible. Given the description of ENSURE-GENERIC-FUNCTION, this also applies to the
CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS function. CLISP's implementation calls CHANGE-CLASS
always, and leaves it to the CHANGE-CLASS function to signal an error if
needed.
Otherwise the generic function generic-function is redefined by calling
the REINITIALIZE-INSTANCE generic function with generic-function and the
initialization arguments. The generic-function argument is then returned.
Methods
(CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS
(generic-function GENERIC-FUNCTION) function-name &KEY
:GENERIC-FUNCTION-CLASS &ALLOW-OTHER-KEYS)This method implements the behavior of the generic
function in the case where function-name names an existing generic
function.
This method can be overridden.
(CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS
(generic-function NULL) function-name &KEY :GENERIC-FUNCTION-CLASS
&ALLOW-OTHER-KEYS)function-name names no function, generic
function, macro or special form.
ADD-METHOD(ADD-METHOD generic-function method)
generic-functionmethodgeneric-function argument.This generic function associates an unattached method with a generic function.
An ERROR is SIGNALed if the lambda list of the method is not
congruent with the lambda list of the generic function.
An ERROR is SIGNALed if the method is already associated with some
other generic function.
If the given method agrees with an existing method of the
generic function on parameter specializers and qualifiers, the
existing method is removed by calling REMOVE-METHOD before the
new method is added. See the [ANSI CL standard] section
7.6.3 “Agreement on
Parameter Specializers and Qualifiers”
for a definition of agreement in this context.
Associating the method with the generic function then proceeds in four steps:
method to the set returned by
CLOS:GENERIC-FUNCTION-METHODS and arrange for CLOS:METHOD-GENERIC-FUNCTION to return generic-function;
CLOS:ADD-DIRECT-METHOD for each of the method's
specializers;CLOS:COMPUTE-DISCRIMINATING-FUNCTION and
install its result with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION; and
The generic function ADD-METHOD can be called by the user
or the implementation.
Methods
(ADD-METHOD
(generic-function STANDARD-GENERIC-FUNCTION)
(method STANDARD-METHOD))(ADD-METHOD
(generic-function STANDARD-GENERIC-FUNCTION)
(method METHOD))REMOVE-METHOD(REMOVE-METHOD generic-function method)
generic-functionmethodgeneric-function argument.This generic function breaks the association between a generic function and one of its methods.
No ERROR is SIGNALed if the method is not among the methods of the
generic function.
Breaking the association between the method and the generic function proceeds in four steps:
method from the set returned by
CLOS:GENERIC-FUNCTION-METHODS and arrange for CLOS:METHOD-GENERIC-FUNCTION to return NIL;
CLOS:REMOVE-DIRECT-METHOD for each of the
method's specializers;CLOS:COMPUTE-DISCRIMINATING-FUNCTION and
install its result with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION;
andThe generic function REMOVE-METHOD can be called by the
user or the implementation.
Methods
(REMOVE-METHOD
(generic-function STANDARD-GENERIC-FUNCTION)
(method STANDARD-METHOD))(REMOVE-METHOD
(generic-function STANDARD-GENERIC-FUNCTION)
(method METHOD))CLOS:COMPUTE-APPLICABLE-METHODS(CLOS:COMPUTE-APPLICABLE-METHODS
generic-function arguments)generic-functionargumentsThis generic function determines the method applicability of a generic function given a list of required arguments. The returned list of method metaobjects is sorted by precedence order with the most specific method appearing first. If no methods are applicable to the supplied arguments the empty list is returned.
When a generic function is invoked, the
discriminating function must determine the ordered list of methods
applicable to the arguments. Depending on the generic function and
the arguments, this is done in one of three ways: using a memoized
value; calling CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES; or calling
CLOS:COMPUTE-APPLICABLE-METHODS.
(Refer to the description of CLOS:COMPUTE-DISCRIMINATING-FUNCTION for
the details of this process.)
The arguments argument is permitted to contain more elements
than the generic function accepts required arguments; in these cases
the extra arguments will be ignored. An ERROR is SIGNALed if arguments
contains fewer elements than the generic function accepts required
arguments.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
Methods
(CLOS:COMPUTE-APPLICABLE-METHODS
(generic-function STANDARD-GENERIC-FUNCTION) arguments)This method SIGNALs an ERROR if any method of the generic
function has a specializer which is neither a class metaobject nor an
EQL specializer metaobject.
Otherwise, this method computes the sorted list of applicable methods according to the rules described in the [ANSI CL standard] section 7.6.6 “Method Selection and Combination”
This method can be overridden. Because of the consistency
requirements between this generic function and
CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES, doing so may require also overriding
.
CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES
(STANDARD-GENERIC-FUNCTION T)
Remarks.
See also the [ANSI CL standard] function COMPUTE-APPLICABLE-METHODS.
CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES(CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES
generic-function classes)generic-functionclassesBOOLEANThis generic function is called to attempt to determine the method applicability of a generic function given only the classes of the required arguments.
If it is possible to completely determine the ordered list of applicable methods based only on the supplied classes, this generic function returns that list as its primary value and true as its second value. The returned list of method metaobjects is sorted by precedence order, the most specific method coming first. If no methods are applicable to arguments with the specified classes, the empty list and true are returned.
If it is not possible to completely determine the ordered list of applicable methods based only on the supplied classes, this generic function returns an unspecified primary value and false as its second value.
When a generic function is invoked, the
discriminating function must determine the ordered list of methods
applicable to the arguments. Depending on the generic function and
the arguments, this is done in one of three ways: using a memoized
value; calling CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES; or calling
CLOS:COMPUTE-APPLICABLE-METHODS.
(Refer to the description of CLOS:COMPUTE-DISCRIMINATING-FUNCTION for
the details of this process.)
The following consistency relationship between
CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES and CLOS:COMPUTE-APPLICABLE-METHODS must
be maintained: for any given generic function and set of arguments,
if CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES returns a second value of true,
the primary value must be equal to the value that would be returned by
a corresponding call to CLOS:COMPUTE-APPLICABLE-METHODS. The results
are undefined if a portable method on either of these generic
functions causes this consistency to be violated.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
Methods
(CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES
(generic-function STANDARD-GENERIC-FUNCTION) classes)If any method of the generic function has a
specializer which is neither a class metaobject nor an EQL
specializer metaobject, this method SIGNALs an ERROR.
In cases where the generic function has no methods with
EQL specializers, or has no methods with EQL specializers
that could be applicable to arguments of the supplied classes, this
method returns the ordered list of applicable methods as its first
value and true as its second value.
Otherwise this method returns an unspecified primary value and false as its second value.
This method can be overridden. Because of the consistency
requirements between this generic function and
CLOS:COMPUTE-APPLICABLE-METHODS, doing so may require also overriding
.
CLOS:COMPUTE-APPLICABLE-METHODS
(STANDARD-GENERIC-FUNCTION T)
This generic function exists to allow user extensions which alter method lookup rules, but which base the new rules only on the classes of the required arguments, to take advantage of the class-based method lookup memoization found in many implementations. (There is of course no requirement for an implementation to provide this optimization.)
Such an extension can be implemented by two methods, one on this
generic function and one on CLOS:COMPUTE-APPLICABLE-METHODS. Whenever
the user extension is in effect, the first method will return a second
value of true. This should allow the implementation to absorb these
cases into its own memoization scheme.
To get appropriate performance, other kinds of extensions may
require methods on CLOS:COMPUTE-DISCRIMINATING-FUNCTION which implement
their own memoization scheme.
CLOS:COMPUTE-EFFECTIVE-METHOD(CLOS:COMPUTE-EFFECTIVE-METHOD generic-function method-combination
methods)generic-functionmethod-combinationmethodsThis generic function is called to determine the effective method from a sorted list of method metaobjects.
An effective method is a form that describes how the
applicable methods are to be combined. Inside of effective method
forms are CALL-METHOD forms which indicate that a particular
method is to be called. The arguments to the CALL-METHOD form
indicate exactly how the method function of the method should be
called. (See CLOS:MAKE-METHOD-LAMBDA for more details about method
functions.)
An effective method option has the same interpretation and
syntax as either the :ARGUMENTS or the :GENERIC-FUNCTION option in the long form
of DEFINE-METHOD-COMBINATION.
More information about the form and interpretation of
effective methods and effective method options can be found under
the description of the DEFINE-METHOD-COMBINATION macro in the
CLOS specification.
This generic function can be called by the user or the implementation. It is called by discriminating functions whenever a sorted list of applicable methods must be converted to an effective method.
Methods
(CLOS:COMPUTE-EFFECTIVE-METHOD
(generic-function STANDARD-GENERIC-FUNCTION) method-combination methods)This method computes the effective method according
to the rules of the method combination type implemented by method-combination.
This method can be overridden.
The second return value may contain only one
:ARGUMENTS option and only one :GENERIC-FUNCTION option. When overriding a
CLOS:COMPUTE-EFFECTIVE-METHOD method, before adding an :ARGUMENTS or
:GENERIC-FUNCTION option, you therefore need to check whether it this option is
already present.
CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION(CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION
generic-function methods arguments)generic-functionmethodsargumentsThis function is called to determine the effective method
from a sorted list of method metaobjects, and convert it to a function.
The arguments are a set of arguments to which the methods are applicable,
and are used solely for error message purposes.
This function calls CLOS:COMPUTE-EFFECTIVE-METHOD using the generic-function's
method combination, wraps local macro definitions for CALL-METHOD and
MAKE-METHOD around it, handles the :ARGUMENTS and :GENERIC-FUNCTION options,
and compiles the resulting form to a function.
CLOS:MAKE-METHOD-LAMBDA(CLOS:MAKE-METHOD-LAMBDA generic-function
method lambda-expression environment)
generic-functionmethodlambda-expressionenvironment&ENVIRONMENT argument to
macro expansion functions.This generic function is called to produce a lambda expression which can itself be used to produce a method function for a method and generic function with the specified classes. The generic function and method the method function will be used with are not required to be the given ones. Moreover, the method metaobject may be uninitialized.
Either the function COMPILE, the special form FUNCTION or
the function COERCE must be used to convert the lambda expression a
method function. The method function itself can be applied to
arguments with APPLY or FUNCALL.
When a method is actually called by an effective method, its
first argument will be a list of the arguments to the generic
function. Its remaining arguments will be all but the first argument
passed to CALL-METHOD. By default, all method functions must
accept two arguments: the list of arguments to the generic function
and the list of next methods.
For a given generic function and method class, the applicable
methods on CLOS:MAKE-METHOD-LAMBDA and CLOS:COMPUTE-EFFECTIVE-METHOD must
be consistent in the following way: each use of CALL-METHOD
returned by the method on CLOS:COMPUTE-EFFECTIVE-METHOD must have the
same number of arguments, and the method lambda returned by the
method on CLOS:MAKE-METHOD-LAMBDA must accept a corresponding number of
arguments.
Note that the system-supplied implementation of
CALL-NEXT-METHOD is not required to handle extra arguments to the
method function. Users who define additional arguments to the method
function must either redefine or forego CALL-NEXT-METHOD. (See the
example below.)
When the method metaobject is created with MAKE-INSTANCE, the method
function must be the value of the :FUNCTION initialization
argument. The additional initialization arguments, returned as the
second value of this generic function, must also be passed in this
call to MAKE-INSTANCE.
Methods
(CLOS:MAKE-METHOD-LAMBDA
(generic-function STANDARD-GENERIC-FUNCTION)
(method STANDARD-METHOD) lambda-expression environment)This method returns a method lambda which accepts two arguments, the list of arguments to the generic function, and the list of next methods. What initialization arguments may be returned in the second value are unspecified.
This method can be overridden.
This example shows how to define a kind of method which, from
within the body of the method, has access to the actual method metaobject for the
method. This simplified code overrides whatever method combination is
specified for the generic function, implementing a simple method
combination supporting only primary methods, CALL-NEXT-METHOD and
NEXT-METHOD-P. (In addition, its a simplified version of
CALL-NEXT-METHOD which does no error checking.)
Notice that the extra lexical function bindings get wrapped around
the body before CALL-NEXT-METHOD is called. In this way, the user's
definition of CALL-NEXT-METHOD and NEXT-METHOD-P are sure to
override the system's definitions.
(defclass my-generic-function (standard-generic-function)
()
(:default-initargs :method-class (find-class 'my-method)))
(defclass my-method (standard-method) ())
(defmethod make-method-lambda ((gf my-generic-function)
(method my-method)
lambda-expression
environment)
(declare (ignore environment))
`(lambda (args next-methods this-method)
(,(call-next-method gf method
`(lambda ,(cadr lambda-expression)
(flet ((this-method () this-method)
(call-next-method (&REST cnm-args)
(funcall (method-function (car next-methods))
(or cnm-args args)
(cdr next-methods)
(car next-methods)))
(next-method-p ()
(not (null next-methods))))
,@(cddr lambda-expression)))
environment)
args next-methods)))
(defmethod compute-effective-method ((gf my-generic-function)
method-combination
methods)
`(call-method ,(car methods) ,(cdr methods) ,(car methods)))
The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented. Its specification is misdesigned: it mixes compile time and
execution time behaviour. The essential problem is: where could the
generic-function argument come from?
DEFMETHOD form occurs in a source file, is
CLOS:MAKE-METHOD-LAMBDA then called at compile time or at load time?
If it was called at compile time, there's no possible value for
the first argument, since the class of the generic function to
which the method will belong is not known until load time. If it
was called at load time, it would mean that the method's source
code could only be compiled at load time, not earlier - which
defeats the purpose of COMPILE-FILEREMOVE-METHOD and then added through ADD-METHOD to a
different generic function, possibly belonging to a different
generic function class, would CLOS:MAKE-METHOD-LAMBDA then be called
again or not? If no, then CLOS:MAKE-METHOD-LAMBDA's first argument is
useless. If yes, then the source code of every method would have
to be present at runtime, and its lexical environment as well.
CALL-METHOD always expect
exactly two arguments: the method and a list of next methods.
CLOS:COMPUTE-DISCRIMINATING-FUNCTION(CLOS:COMPUTE-DISCRIMINATING-FUNCTION
generic-function)generic-functionThis generic function is called to determine the discriminating function for a generic function. When a generic function is called, the installed discriminating function is called with the full set of arguments received by the generic function, and must implement the behavior of calling the generic function: determining the ordered set of applicable methods, determining the effective method, and running the effective method.
To determine the ordered set of applicable methods, the
discriminating function first calls CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES.
If CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES returns a second value of false,
the discriminating function then calls CLOS:COMPUTE-APPLICABLE-METHODS.
When CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES returns a second
value of true, the discriminating function is permitted to memoize
the primary value as follows. The discriminating function may
reuse the list of applicable methods without calling
CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES again provided that:
Determination of the effective method is done by calling
CLOS:COMPUTE-EFFECTIVE-METHOD. When the effective method is run, each
method's function is called, and receives as arguments:
CALL-METHOD form indicating that the method should be called.
(See CLOS:MAKE-METHOD-LAMBDA for more information about how method
functions are called.)
The generic function CLOS:COMPUTE-DISCRIMINATING-FUNCTION is
called, and its result installed, by ADD-METHOD, REMOVE-METHOD,
INITIALIZE-INSTANCE and REINITIALIZE-INSTANCE.
Methods
(CLOS:COMPUTE-DISCRIMINATING-FUNCTION
(generic-function STANDARD-GENERIC-FUNCTION))No behavior is specified for this method beyond that which is specified for the generic function.
This method can be overridden.
Overriding methods can make use of the function
CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION. It is more convenient to call
CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION than CLOS:COMPUTE-EFFECTIVE-METHOD
because the in the latter case one needs a lot of “glue
code” for implementing the local macros CALL-METHOD and
MAKE-METHOD, and this glue code is implementation dependent because
it needs
CLOS:COMPUTE-EFFECTIVE-METHOD.
The reader generic functions which simply return information associated with method metaobjects are presented together here in the format described in Section 29.3.3, “Introspection: Readers for class metaobjects”.
Each of these reader generic functions have the same syntax,
accepting one required argument called method, which must be a
method metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed
if the method metaobject has not been initialized.
These generic functions can be called by the user or the implementation.
For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.
CLOS:METHOD-SPECIALIZERS(CLOS:METHOD-SPECIALIZERS method)Returns a list of the specializers of method. This value is a
list of specializer metaobjects. This is the value of the
:SPECIALIZERS initialization argument that was associated with the
method during initialization.
METHOD-QUALIFIERS(METHOD-QUALIFIERS method)Returns a (possibly empty) list of the qualifiers of method.
This value is a list of non-NIL atoms. This is the defaulted value of
the :QUALIFIERS initialization argument that was associated with the
method during initialization.
CLOS:METHOD-LAMBDA-LIST(CLOS:METHOD-LAMBDA-LIST method)Returns the (unspecialized) lambda list of method. This value
is a Common Lisp lambda list. This is the value of the :LAMBDA-LIST
initialization argument that was associated with the method during
initialization.
CLOS:METHOD-GENERIC-FUNCTION(CLOS:METHOD-GENERIC-FUNCTION method)Returns the generic function that method is currently
connected to, or NIL if it is not currently connected to any generic
function. This value is either a generic function metaobject or NIL.
When a method is first created it is not connected to any generic
function. This connection is maintained by the generic functions
ADD-METHOD and REMOVE-METHOD.
CLOS:METHOD-FUNCTION(CLOS:METHOD-FUNCTION method)Returns the method function of method. This is the
value of the :FUNCTION initialization argument that was associated
with the method during initialization.
The specified methods for the method metaobject readers
(CLOS:METHOD-SPECIALIZERS
(method STANDARD-METHOD))(METHOD-QUALIFIERS
(method STANDARD-METHOD))(CLOS:METHOD-LAMBDA-LIST
(method STANDARD-METHOD))(CLOS:METHOD-FUNCTION
(method STANDARD-METHOD))(CLOS:METHOD-GENERIC-FUNCTION
(method STANDARD-METHOD))No behavior is specified for this method beyond that which is specified for the generic function.
The value returned by this method is maintained by
and
ADD-METHOD(STANDARD-GENERIC-FUNCTION
STANDARD-METHOD).REMOVE-METHOD(STANDARD-GENERIC-FUNCTION
STANDARD-METHOD)
DEFMETHODThe evaluation or execution of a DEFMETHOD form requires first
that the body of the method be converted to a method function.
This process is described
below.
The result of this process is a method function and a set of additional
initialization arguments to be used when creating the new method.
Given these two values, the evaluation or execution of a DEFMETHOD
form proceeds in three steps.
The first step ensures the existence of a generic function with
the specified name. This is done by calling the function ENSURE-GENERIC-FUNCTION.
The first argument in this call is the generic function name specified
in the DEFMETHOD form.
The second step is the creation of the new method metaobject by calling
MAKE-INSTANCE. The class of the new method metaobject is determined by calling
CLOS:GENERIC-FUNCTION-METHOD-CLASS on the result of the call to ENSURE-GENERIC-FUNCTION from the
first step.
The initialization arguments received by the call to MAKE-INSTANCE
are as follows:
:QUALIFIERS initialization
argument is a list of the qualifiers which appeared in the DEFMETHOD
form. No special processing is done on these values. The order of the
elements of this list is the same as in the DEFMETHOD form.
:LAMBDA-LIST initialization
argument is the unspecialized lambda list from the DEFMETHOD form.
:SPECIALIZERS initialization
argument is a list of the specializers for the method. For specializers
which are classes, the specializer is the class metaobject itself. In
the case of EQL specializers, it will be an CLOS:EQL-SPECIALIZER
metaobject obtained by calling CLOS:INTERN-EQL-SPECIALIZER on the result of
evaluating the EQL specializer form in the lexical environment of the
DEFMETHOD form.:FUNCTION initialization
argument is the method function.The value of the :DECLARATIONS initialization
argument is a list of the declaration specifiers from the DEFMETHOD form.
If there are no declarations in the macro form, this initialization argument
either does not appear, or appears with a value of the empty list.
No :DECLARATIONS initialization argument is
provided, because method initialization does not support a :DECLARATIONS
argument, and because the method function is already completely provided
through the :FUNCTION initialization argument.
:DOCUMENTATION initialization
argument is the documentation string from the DEFMETHOD form. If
there is no documentation string in the macro form this initialization
argument either does not appear, or appears with a value of false.
In the third step, ADD-METHOD is called to add the newly created
method to the set of methods associated with the generic function metaobject.
The result of the call to ADD-METHOD is returned as the result
of evaluating or executing the DEFMETHOD form.
An example showing a typical DEFMETHOD form and a sample
expansion is shown in the following example:
An example DEFMETHOD form and one possible correct
expansion. In the expansion, method-lambda
is the result of calling CLOS:MAKE-METHOD-LAMBDA as described in
Section 29.6.3.1.1, “Processing Method Bodies”.
The initargs appearing after :FUNCTION are assumed to be additional
initargs returned from the call to CLOS:MAKE-METHOD-LAMBDA.
(defmethod move :before ((p position) (l (eql 0))
&OPTIONAL (visiblyp t)
&KEY color)
(set-to-origin p)
(when visiblyp (show-move p 0 color)))
(let ((#:g001 (ensure-generic-function 'move)))
(add-method #:g001
(make-instance (generic-function-method-class #:g001)
:qualifiers '(:before)
:specializers (list (find-class 'position)
(intern-eql-specializer 0))
:lambda-list '(p l &OPTIONAL (visiblyp t)
&KEY color)
:function (function method-lambda)
'additional-initarg-1 't
'additional-initarg-2 '39)))
The processing of the method body for this method is shown below.
Before a method can be created, the list of forms comprising the method body must be converted to a method function. This conversion is a two step process.
The body of methods can also appear in the
:METHOD option of DEFGENERIC forms. Initial methods are
not considered by any of the protocols specified in this document.
During macro-expansion of the DEFMETHOD macro shown in
the previous example code
similar to this would be run to produce the method lambda and
additional initargs. In this example, environment is the macroexpansion
environment of the DEFMETHOD macro form.
(let ((gf (ensure-generic-function 'move)))
(make-method-lambda
gf
(class-prototype (generic-function-method-class gf))
'(lambda (p l &OPTIONAL (visiblyp t) &KEY color)
(set-to-origin p)
(when visiblyp (show-move p 0 color)))
environment))
The first step occurs during macro-expansion of the macro form. In this step, the method lambda list, declarations and body are converted to a lambda expression called a method lambda . This conversion is based on information associated with the generic function definition in effect at the time the macro form is expanded.
The generic function definition is obtained by calling ENSURE-GENERIC-FUNCTION with
a first argument of the generic function name specified in the macro form.
The :LAMBDA-LIST keyword argument is not passed in this call.
Given the generic function, production of the method lambda
proceeds by calling CLOS:MAKE-METHOD-LAMBDA.
The first argument in this call is the generic function obtained as
described above.
The second argument is the result of calling CLOS:CLASS-PROTOTYPE on the
result of calling CLOS:GENERIC-FUNCTION-METHOD-CLASS on the generic function.
The third argument is a lambda expression formed from the method lambda list,
declarations and body.
The fourth argument is the macro-expansion environment of the macro
form; this is the value of the &ENVIRONMENT argument to the
DEFMETHOD macro.
The generic function CLOS:MAKE-METHOD-LAMBDA returns two values.
The first is the method lambda itself.
The second is a list of initialization arguments and values. These are
included in the initialization arguments when the method is created.
In the second step, the method lambda is converted to a function
which properly captures the lexical scope of the macro form. This is
done by having the method lambda appear in the macro-expansion as the
argument of the FUNCTION special form. During the subsequent
evaluation of the macro-expansion, the result of the FUNCTION special
form is the method function.
See The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented.
An example of creating a generic function and a method metaobject, and then adding the method to the generic function is shown below. This example is comparable to the method definition shown above:
(let* ((gf (make-instance 'standard-generic-function
:lambda-list '(p l &OPTIONAL visiblyp &KEY)))
(method-class (generic-function-method-class gf)))
(multiple-value-bind (lambda initargs)
(make-method-lambda
gf
(class-prototype method-class)
'(lambda (p l &OPTIONAL (visiblyp t) &KEY color)
(set-to-origin p)
(when visiblyp (show-move p 0 color)))
nil)
(add-method gf
(apply #'make-instance method-class
:function (compile nil lambda)
:specializers (list (find-class 'position)
(intern-eql-specializer 0))
:qualifiers ()
:lambda-list '(p l &OPTIONAL (visiblyp t)
&KEY color)
initargs))))
Methods created through DEFMETHOD have a faster calling
convention than methods created through a portable MAKE-INSTANCE
invocation.
A method metaobject can be created by calling MAKE-INSTANCE.
The initialization arguments establish the definition of the method.
A method metaobject cannot be redefined;
calling REINITIALIZE-INSTANCE SIGNALs an ERROR.
Initialization of a method metaobject must be done by calling MAKE-INSTANCE
and allowing it to call INITIALIZE-INSTANCE. Portable programs must
not
INITIALIZE-INSTANCE directly to
initialize a method metaobject;SHARED-INITIALIZE directly to
initialize a method metaobject;CHANGE-CLASS to change the class of any
method metaobject or to turn a non-method object into a method metaobject.
Since metaobject classes may not be redefined,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-REDEFINED-CLASS on method metaobjects.
Since the class of a method metaobject cannot be changed,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on method metaobjects.
During initialization, each initialization argument is checked for errors and then associated with the method metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.5, “Initialization arguments and accessors for method metaobjects”.
This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. The section ends with a set of restrictions on portable methods affecting method metaobject initialization.
In these descriptions, the phrase “this argument defaults to
value” means that when that initialization argument is not
supplied, initialization is performed as if value had been supplied.
For some initialization arguments this could be done by the use of
default initialization arguments, but whether it is done this way is not
specified. Implementations are free to define default initialization
arguments for specified method metaobject classes. Portable programs
are free to define default initialization arguments for portable
subclasses of the class METHOD.
:QUALIFIERS argument is a list of method
qualifiers. An ERROR is SIGNALed if this value is not a proper list, or if
any element of the list is not a non-null atom. This argument
defaults to the empty list.:LAMBDA-LIST argument is the unspecialized
lambda list of the method. An ERROR is SIGNALed if this value is not a
proper lambda list. If this value is not supplied, an ERROR is SIGNALed.
:SPECIALIZERS argument is a list of the
specializer metaobjects for the method. An ERROR is SIGNALed if this value
is not a proper list, or if the length of the list differs from the
number of required arguments in the :LAMBDA-LIST argument, or if
any element of the list is not a specializer metaobject. If this
value is not supplied, an ERROR is SIGNALed.:FUNCTION argument is a method function. It
must be compatible with the methods on CLOS:COMPUTE-EFFECTIVE-METHOD
defined for this class of method and generic function with which it
will be used. That is, it must accept the same number of arguments
as all uses of CALL-METHOD that will call it supply. (See
CLOS:COMPUTE-EFFECTIVE-METHOD and CLOS:MAKE-METHOD-LAMBDA for more information.)
An ERROR is SIGNALed if this argument is not supplied.CLOS:STANDARD-ACCESSOR-METHOD, the :SLOT-DEFINITION
initialization argument must be provided. Its value is the direct
slot definition metaobject which defines this accessor method. An ERROR is SIGNALed if the value
is not an instance of a subclass of CLOS:DIRECT-SLOT-DEFINITION.:DOCUMENTATION argument is a string or NIL.
An ERROR is SIGNALed if this value is not a string or NIL. This argument
defaults to NIL.After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the method metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:
Table 29.5. Initialization arguments and accessors for method metaobjects
| Initialization Argument | Generic Function |
|---|---|
:QUALIFIERS | METHOD-QUALIFIERS |
:LAMBDA-LIST | CLOS:METHOD-LAMBDA-LIST |
:SPECIALIZERS | CLOS:METHOD-SPECIALIZERS |
:FUNCTION | CLOS:METHOD-FUNCTION |
:SLOT-DEFINITION | CLOS:ACCESSOR-METHOD-SLOT-DEFINITION |
:DOCUMENTATION | DOCUMENTATION |
It is not specified which methods provide the initialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented in as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the method metaobject when either all or none of the specified initialization has taken effect.
These restrictions govern the methods that a portable program can
define on the generic functions INITIALIZE-INSTANCE,
REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions
apply only to methods on these generic functions for which the first
specializer is a subclass of the class METHOD. Other portable
methods on these generic functions are not affected by these
restrictions.
SHARED-INITIALIZE or REINITIALIZE-INSTANCE.For INITIALIZE-INSTANCE:
The results are undefined if any of these restrictions are violated.
CLOS:EXTRACT-LAMBDA-LIST(CLOS:EXTRACT-LAMBDA-LIST specialized-lambda-list)
specialized-lambda-listDEFMETHOD.
This function takes a specialized lambda list and returns the lambda list with the specializers removed. This is a non-destructive operation. Whether the result shares any structure with the argument is unspecified.
If the specialized-lambda-list argument does not have legal syntax,
an ERROR is SIGNALed. This syntax checking does not check the syntax of the
actual specializer names, only the syntax of the lambda list and
where the specializers appear.
(CLOS:EXTRACT-LAMBDA-LIST'((p position))) ⇒(P)(CLOS:EXTRACT-LAMBDA-LIST'((p position) x y)) ⇒(P X Y)(CLOS:EXTRACT-LAMBDA-LIST'(a (b (eql x)) c&RESTi)) ⇒(A B C&OPTIONALI)
CLOS:EXTRACT-SPECIALIZER-NAMES(CLOS:EXTRACT-SPECIALIZER-NAMES
specialized-lambda-list)specialized-lambda-listDEFMETHOD.
This function takes a specialized lambda list and returns its specializer names. This is a non-destructive operation. Whether the result shares structure with the argument is unspecified.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
The result of this function will be a list with a
number of elements equal to the number of required arguments in
specialized-lambda-list. Specializers are defaulted to the symbol T.
If the specialized-lambda-list argument does not have legal
syntax, an ERROR is SIGNALed. This syntax checking does not check the syntax
of the actual specializer names, only the syntax of the lambda list
and where the specializers appear.
(CLOS:EXTRACT-SPECIALIZER-NAMES'((p position))) ⇒(POSITION)(CLOS:EXTRACT-SPECIALIZER-NAMES'((p position) x y)) ⇒(POSITION T T)(CLOS:EXTRACT-SPECIALIZER-NAMES'(a (b (eql x)) c&RESTi)) ⇒(T (EQL X) T)
CLOS:ACCESSOR-METHOD-SLOT-DEFINITION(CLOS:ACCESSOR-METHOD-SLOT-DEFINITION method)This accessor can only be called on accessor methods. It returns
the direct slot definition metaobject that defined this method. This is the value of the
:SLOT-DEFINITION initialization argument associated with the method during
initialization.
The specified methods for the accessor method metaobject readers
(CLOS:ACCESSOR-METHOD-SLOT-DEFINITION
(method CLOS:STANDARD-ACCESSOR-METHOD))CLOS:READER-METHOD-CLASS(CLOS:READER-METHOD-CLASS class direct-slot-definition
&REST initargs)classdirect-slot-definitioninitargsThis generic function is called to determine the
class of reader methods created during class initialization and
reinitialization. The result must be a subclass of
CLOS:STANDARD-READER-METHOD.
The initargs argument must be the same as will be passed
to MAKE-INSTANCE to create the reader method. The initargs
must include :SLOT-DEFINITION with slot-definition as its value.
Methods
(CLOS:READER-METHOD-CLASS
(class STANDARD-CLASS) (direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION)
&REST initargs)(CLOS:READER-METHOD-CLASS
(class CLOS:FUNCALLABLE-STANDARD-CLASS) (direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION)
&REST initargs)These methods return the class
CLOS:STANDARD-READER-METHOD.
These methods can be overridden.
CLOS:WRITER-METHOD-CLASS(CLOS:WRITER-METHOD-CLASS class
direct-slot &REST initargs)
classdirect-slotinitargsThis generic function is called to determine the
class of writer methods created during class initialization and
reinitialization. The result must be a subclass of
CLOS:STANDARD-WRITER-METHOD.
The initargs argument must be the same as will be passed
to MAKE-INSTANCE to create the reader method. The initargs
must include :SLOT-DEFINITION with CLOS:SLOT-DEFINITION as its value.
Methods
(CLOS:WRITER-METHOD-CLASS
(class STANDARD-CLASS)
(direct-slot CLOS:STANDARD-DIRECT-SLOT-DEFINITION)
&REST initargs)(CLOS:WRITER-METHOD-CLASS
(class CLOS:FUNCALLABLE-STANDARD-CLASS)
(direct-slot CLOS:STANDARD-DIRECT-SLOT-DEFINITION)
&REST initargs)These methods return the class
CLOS:STANDARD-WRITER-METHOD.
These methods can be overridden.
CLOS:EQL-SPECIALIZER-OBJECT(CLOS:EQL-SPECIALIZER-OBJECT
eql-specializer)
eql-specializerEQL specializer metaobject.
This function returns the object associated with
eql-specializer during initialization.
The value is guaranteed to be EQL to the value originally passed
to CLOS:INTERN-EQL-SPECIALIZER, but it is not necessarily EQ to that
value.
This function SIGNALs an ERROR if
eql-specializer is not an EQL
specializer.
CLOS:INTERN-EQL-SPECIALIZER(CLOS:INTERN-EQL-SPECIALIZER
object)objectEQL specializer metaobject for object.
EQL specializer
metaobject for object, creating one if necessary. Two calls to
CLOS:INTERN-EQL-SPECIALIZER with EQL arguments will return the same
(i.e., EQ) value.Remarks. The result of calling CLOS:EQL-SPECIALIZER-OBJECT on the result of a
call to CLOS:INTERN-EQL-SPECIALIZER is only guaranteed to be EQL to the
original object argument, not necessarily EQ.
CLOS:SPECIALIZER-DIRECT-METHODS(CLOS:SPECIALIZER-DIRECT-METHODS
specializer)specializerspecializer as a specializer. The elements of this set are
method metaobjects. This value is maintained by the generic
functions CLOS:ADD-DIRECT-METHOD and CLOS:REMOVE-DIRECT-METHOD.
Methods
(CLOS:SPECIALIZER-DIRECT-METHODS
(specializer CLASS))No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:SPECIALIZER-DIRECT-METHODS
(specializer CLOS:EQL-SPECIALIZER))CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS(CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
specializer)specializerspecializer
as a specializer. The elements of this set are generic function metaobjects. This value
is maintained by the generic functions CLOS:ADD-DIRECT-METHOD and
CLOS:REMOVE-DIRECT-METHOD.Methods
(CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
(specializer CLASS))No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
(specializer CLOS:EQL-SPECIALIZER))CLOS:ADD-DIRECT-METHOD(CLOS:ADD-DIRECT-METHOD
specializer method)specializermethodThis generic function is called to maintain a set of
backpointers from a specializer to the set of methods specialized to
it. If method is already in the set, it is not added again (no
ERROR is SIGNALed).
This set can be accessed as a list by calling the generic
function CLOS:SPECIALIZER-DIRECT-METHODS. Methods are removed from the
set by CLOS:REMOVE-DIRECT-METHOD.
The generic function CLOS:ADD-DIRECT-METHOD is called by
ADD-METHOD whenever a method is added to a generic function. It is
called once for each of the specializers of the method. Note that in
cases where a specializer appears more than once in the specializers
of a method, this generic function will be called more than once with
the same specializer as argument.
The results are undefined if the specializer argument
is not one of the specializers of the method argument.
Methods
(CLOS:ADD-DIRECT-METHOD
(specializer CLASS) (method METHOD))This method implements the behavior of the generic function for class specializers.
No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:ADD-DIRECT-METHOD
(specializer CLOS:EQL-SPECIALIZER)
(method METHOD))This method implements the behavior of the generic
function for EQL specializers.
No behavior is specified for this method beyond that which is specified for the generic function.
CLOS:REMOVE-DIRECT-METHOD(CLOS:REMOVE-DIRECT-METHOD specializer
method)specializermethodThis generic function is called to maintain a set of
backpointers from a specializer to the set of methods specialized to
it. If method is in the set it is removed. If it is not, no
ERROR is SIGNALed.
This set can be accessed as a list by calling the generic
function CLOS:SPECIALIZER-DIRECT-METHODS. Methods are added to the set
by CLOS:ADD-DIRECT-METHOD.
The generic function CLOS:REMOVE-DIRECT-METHOD is called by
REMOVE-METHOD whenever a method is removed from a generic function.
It is called once for each of the specializers of the method. Note
that in cases where a specializer appears more than once in the
specializers of a method, this generic function will be called more
than once with the same specializer as argument.
The results are undefined if the specializer argument is
not one of the specializers of the method argument.
Methods
(CLOS:REMOVE-DIRECT-METHOD
(specializer CLASS) (method METHOD))This method implements the behavior of the generic function for class specializers.
No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:REMOVE-DIRECT-METHOD
(specializer CLOS:EQL-SPECIALIZER)
(method METHOD))This method implements the behavior of the generic
function for EQL specializers.
No behavior is specified for this method beyond that which is specified for the generic function.
CLOS:FIND-METHOD-COMBINATION(CLOS:FIND-METHOD-COMBINATION generic-function
method-combination-type-name
method-combination-options)
generic-functionmethod-combination-type-namemethod-combination-optionsRemarks. Further details of method combination metaobjects are not specified.
CLOS:STANDARD-INSTANCE-ACCESSCLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESSCLOS:SET-FUNCALLABLE-INSTANCE-FUNCTIONCLOS:SLOT-VALUE-USING-CLASS(SETF CLOS:SLOT-VALUE-USING-CLASS)CLOS:SLOT-BOUNDP-USING-CLASSCLOS:SLOT-MAKUNBOUND-USING-CLASSThe instance structure protocol is responsible for implementing
the behavior of the slot access functions like SLOT-VALUE and
(.SETF SLOT-VALUE)
For each CLOS slot access function other than SLOT-EXISTS-P,
there is a corresponding generic function which actually provides the
behavior of the function. When called, the slot access function finds
the pertinent effective slot definition metaobject, calls the corresponding generic function and
returns its result. The arguments passed on to the generic function
include one additional value, the class of the object argument,
which always immediately precedes the object argument.
Table 29.6. The correspondence between slot access function and underlying slot access generic function
| Slot Access Function | Corresponding Slot Access Generic Function |
|---|---|
SLOT-VALUE object slot-name | CLOS:SLOT-VALUE-USING-CLASS class object slot |
( new-value object slot-name | (SETF CLOS:SLOT-VALUE-USING-CLASS) new-value class object slot |
SLOT-BOUNDP object slot-name | CLOS:SLOT-BOUNDP-USING-CLASS class object slot |
SLOT-MAKUNBOUND object slot-name | CLOS:SLOT-MAKUNBOUND-USING-CLASS class object slot |
At the lowest level, the instance structure protocol provides only limited mechanisms for portable programs to control the implementation of instances and to directly access the storage associated with instances without going through the indirection of slot access. This is done to allow portable programs to perform certain commonly requested slot access optimizations.
In particular, portable programs can control the implementation
of, and obtain direct access to, slots with allocation :INSTANCE and
type T. These are called directly accessible slots
.
The relevant specified around-method on CLOS:COMPUTE-SLOTS determines
the implementation of instances by deciding how each slot in the
instance will be stored. For each directly accessible slot, this method
allocates a location
and associates it with the effective slot definition metaobject.
The location can be accessed by calling the CLOS:SLOT-DEFINITION-LOCATION
generic function. Locations are non-negative integers. For a given
class, the locations increase consecutively, in the order that the
directly accessible slots appear in the list of effective slots. (Note
that here, the next paragraph, and the specification of this
around-method are the only places where the value returned by
CLOS:COMPUTE-SLOTS is described as a list rather than a set.)
Given the location of a directly accessible slot, the value of
that slot in an instance can be accessed with the appropriate accessor.
For STANDARD-CLASS, this accessor is the function
CLOS:STANDARD-INSTANCE-ACCESS. For CLOS:FUNCALLABLE-STANDARD-CLASS, this
accessor is the function CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS.
In each case, the arguments to the accessor are the instance and the
slot location, in that order. See the definition of each accessor for
additional restrictions on the use of these function.
Portable programs are permitted to affect and rely on the
allocation of locations only in the following limited way: By first
defining a portable primary method on CLOS:COMPUTE-SLOTS which orders the
returned value in a predictable way, and then relying on the defined
behavior of the specified around-method to assign locations to all
directly accessible slots. Portable programs may compile-in calls to
low-level accessors which take advantage of the resulting predictable
allocation of slot locations.
This example shows the use of this mechanism to implement a new
class metaobject class, ordered-class and class
option :SLOT-ORDER. This option provides control
over the allocation of slot locations. In this simple example
implementation, the :SLOT-ORDER option is not
inherited by subclasses; it controls only instances of the class
itself.
(defclass ordered-class (standard-class)
((slot-order :initform ()
:initarg :slot-order
:reader class-slot-order)))
(defmethod compute-slots ((class ordered-class))
(let ((order (class-slot-order class)))
(sort (copy-list (call-next-method))
#'(lambda (a b)
(< (position (slot-definition-name a) order)
(position (slot-definition-name a) order))))))
Following is the source code the user of this extension would write.
Note that because the code above does not implement inheritance of
the :SLOT-ORDER option, the function
distance must not be called on instances of
subclasses of point; it can only be called on
instances of point itself.
(defclass point ()
((x :initform 0)
(y :initform 0))
(:metaclass ordered-class)
(:slot-order x y))
(defun distance (point)
(sqrt (/ (+ (expt (standard-instance-access point 0) 2)
(expt (standard-instance-access point 1) 2))
2.0)))
You cannot assume that the slot-location
values start at 0. In class point, for
example, x and y will be at slot locations 1 and 2, not 0 and
1.
In more realistic uses of this mechanism, the calls to the low-level instance structure accessors would not actually appear textually in the source program, but rather would be generated by a meta-level analysis program run during the process of compiling the source program.
Instances of classes which are themselves instances of
CLOS:FUNCALLABLE-STANDARD-CLASS or one of its subclasses are called
funcallable instances.
Funcallable instances can only be created by
.ALLOCATE-INSTANCE
(CLOS:FUNCALLABLE-STANDARD-CLASS)
Like standard instances, funcallable instances have slots with the
normal behavior. They differ from standard instances in that they can
be used as functions as well; that is, they can be passed to FUNCALL
and APPLY, and they can be stored as the definition of a function
name. Associated with each funcallable instance is the function which
it runs when it is called. This function can be changed with
CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION.
The following simple example shows the use of funcallable
instances to create a simple, DEFSTRUCT-like facility. (Funcallable
instances are useful when a program needs to construct and maintain a
set of functions and information about those functions. They make it
possible to maintain both as the same object rather than two separate
objects linked, for example, by hash tables.)
(defclass constructor () ((name :initarg :name :accessor constructor-name) (fields :initarg :fields :accessor constructor-fields)) (:metaclass funcallable-standard-class)) ⇒#>FUNCALLABLE-STANDARD-CLASS CONSTRUCTOR>(defmethod initialize-instance :after ((c constructor)&KEY) (with-slots (name fields) c (set-funcallable-instance-function c #'(lambda () (let ((new (make-array (1+ (length fields))))) (setf (aref new 0) name) new))))) ⇒#<STANDARD-METHOD :AFTER (#<FUNCALLABLE-STANDARD-CLASS CONSTRUCTOR>)>(setq c1 (make-instance 'constructor :name 'position :fields '(x y))) ⇒#<CONSTRUCTOR #<UNBOUND>>(setq p1 (funcall c1)) ⇒#(POSITION NIL NIL)
CLOS:STANDARD-INSTANCE-ACCESSCLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESSCLOS:SET-FUNCALLABLE-INSTANCE-FUNCTIONCLOS:SLOT-VALUE-USING-CLASS(SETF CLOS:SLOT-VALUE-USING-CLASS)CLOS:SLOT-BOUNDP-USING-CLASSCLOS:SLOT-MAKUNBOUND-USING-CLASSCLOS:STANDARD-INSTANCE-ACCESS(CLOS:STANDARD-INSTANCE-ACCESS
instance location)instancelocationThis function is called to provide direct access to a slot in an instance. By usurping the normal slot lookup protocol, this function is intended to provide highly optimized access to the slots associated with an instance.
The following restrictions apply to the use of this function:
instance argument must be a
standard instance (it must have been returned by
ALLOCATE-INSTANCE(STANDARD-CLASS)).
instance argument cannot be an
non-updated obsolete instance.location argument must be a location of
one of the directly accessible slots of the instance's class.
The results are undefined if any of these restrictions are violated.
CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS(CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS
instance location)instancelocationThis function is called to provide direct access to a slot in an instance. By usurping the normal slot lookup protocol, this function is intended to provide highly optimized access to the slots associated with an instance.
The following restrictions apply to the use of this function:
instance argument must be a
funcallable instance (it must have been returned by
ALLOCATE-INSTANCE
(CLOS:FUNCALLABLE-STANDARD-CLASS)).instance argument cannot be an
non-updated obsolete instance.location argument must be a location of
one of the directly accessible slots of the instance's class.
The results are undefined if any of these restrictions are violated.
CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION(CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION
funcallable-instance function)
funcallable-instanceALLOCATE-INSTANCE
(CLOS:FUNCALLABLE-STANDARD-CLASS)).
functionCLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION is called, any subsequent calls
to funcallable-instance will run the new
function.CLOS:SLOT-VALUE-USING-CLASS(CLOS:SLOT-VALUE-USING-CLASS class
object slot)classobject argument.objectslotThis generic function implements the behavior of the
SLOT-VALUE function. It is called by SLOT-VALUE with the class
of object as its first argument and the pertinent effective slot definition metaobject as its
third argument.
The generic function CLOS:SLOT-VALUE-USING-CLASS returns the value
contained in the given slot of the given object. If the slot is
unbound, SLOT-UNBOUND is called.
The results are undefined if
the class argument is not the class of the object argument, or
if the slot argument does not appear among the set of effective
slots associated with the class argument.
Methods
(CLOS:SLOT-VALUE-USING-CLASS
(class STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))(CLOS:SLOT-VALUE-USING-CLASS
(class CLOS:FUNCALLABLE-STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))These methods implement
the full behavior of this generic function for slots with allocation
:INSTANCE and :CLASS. If the supplied slot has an allocation
other than :INSTANCE or :CLASS an ERROR is SIGNALed.
Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.
(CLOS:SLOT-VALUE-USING-CLASS
(class BUILT-IN-CLASS) object slot)SIGNALs an ERROR.
(SETF CLOS:SLOT-VALUE-USING-CLASS)((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value class
object slot)new-valueclassobject argument.objectslotnew-value argument.The generic function (SETF CLOS:SLOT-VALUE-USING-CLASS) implements
the behavior of the ( function. It is called by
SETF SLOT-VALUE)( with the class of SETF SLOT-VALUE)object as its second argument
and the pertinent effective slot definition metaobject as its fourth argument.
The generic function (SETF CLOS:SLOT-VALUE-USING-CLASS) sets the value
contained in the given slot of the given object to the given new
value; any previous value is lost.
The results are undefined if
the class argument is not the class of the object argument, or
if the slot argument does not appear among the set of effective
slots associated with the class argument.
Methods
((SETF CLOS:SLOT-VALUE-USING-CLASS)
new-value (class STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))((SETF CLOS:SLOT-VALUE-USING-CLASS)
new-value (class CLOS:FUNCALLABLE-STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))These methods implement
the full behavior of this generic function for slots with allocation
:INSTANCE and :CLASS. If the supplied slot has an allocation
other than :INSTANCE or :CLASS an ERROR is SIGNALed.
Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.
((SETF CLOS:SLOT-VALUE-USING-CLASS)
new-value (class BUILT-IN-CLASS) object slot)SIGNALs an ERROR.
CLOS:SLOT-BOUNDP-USING-CLASS(CLOS:SLOT-BOUNDP-USING-CLASS class object
slot)classobject argument.objectslotBOOLEANThis generic function implements the behavior of the
SLOT-BOUNDP function. It is called by SLOT-BOUNDP with the class
of object as its first argument and the pertinent effective slot definition metaobject as its
third argument.
The generic function CLOS:SLOT-BOUNDP-USING-CLASS tests whether a
specific slot in an instance is bound.
The results are undefined if
the class argument is not the class of the object argument, or
if the slot argument does not appear among the set of effective
slots associated with the class argument.
Methods
(CLOS:SLOT-BOUNDP-USING-CLASS
(class STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))(CLOS:SLOT-BOUNDP-USING-CLASS
(class CLOS:FUNCALLABLE-STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))These methods implement
the full behavior of this generic function for slots with allocation
:INSTANCE and :CLASS. If the supplied slot has an allocation
other than :INSTANCE or :CLASS an ERROR is SIGNALed.
Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.
(CLOS:SLOT-BOUNDP-USING-CLASS
(class BUILT-IN-CLASS) object slot)SIGNALs an ERROR.Remarks. In cases where the class metaobject class does not distinguish unbound slots, true should be returned.
CLOS:SLOT-MAKUNBOUND-USING-CLASS(CLOS:SLOT-MAKUNBOUND-USING-CLASS class object
slot)classobject argument.objectslotobject argument.This generic function implements the behavior of the
SLOT-MAKUNBOUND function. It is called by SLOT-MAKUNBOUND with
the class of object as its first argument and the pertinent
effective slot definition metaobject as its third argument.
The generic function CLOS:SLOT-MAKUNBOUND-USING-CLASS restores a slot in
an object to its unbound state. The interpretation
of “restoring a slot to its unbound state” depends on
the class metaobject class.
The results are undefined if
the class argument is not the class of the object argument, or
if the slot argument does not appear among the set of effective
slots associated with the class argument.
Methods
(CLOS:SLOT-MAKUNBOUND-USING-CLASS
(class STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))(CLOS:SLOT-MAKUNBOUND-USING-CLASS
(class CLOS:FUNCALLABLE-STANDARD-CLASS) object
(slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))These methods implement
the full behavior of this generic function for slots with allocation
:INSTANCE and :CLASS. If the supplied slot has an allocation
other than :INSTANCE or :CLASS an ERROR is SIGNALed.
Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.
(CLOS:SLOT-MAKUNBOUND-USING-CLASS
(class BUILT-IN-CLASS) object slot)SIGNALs an ERROR.
It is convenient for portable metaobjects to be able to memoize information about other metaobjects, portable or otherwise. Because class and generic function metaobjects can be reinitialized, and generic function metaobjects can be modified by adding and removing methods, a means must be provided to update this memoized information.
The dependent maintenance protocol supports this by providing a
way to register an object which should be notified whenever a class or
generic function is modified. An object which has been registered this
way is called a dependent of the class or generic function metaobject.
The dependents of class and generic function metaobjects are maintained with CLOS:ADD-DEPENDENT
and CLOS:REMOVE-DEPENDENT. The dependents of a class or generic function metaobject can be
accessed with CLOS:MAP-DEPENDENTS. Dependents are notified about a
modification by calling CLOS:UPDATE-DEPENDENT. (See the specification of
CLOS:UPDATE-DEPENDENT for detailed description of the circumstances under
which it is called.)
To prevent conflicts between two portable programs, or between portable programs and the implementation, portable code must not register metaobjects themselves as dependents. Instead, portable programs which need to record a metaobject as a dependent, should encapsulate that metaobject in some other kind of object, and record that object as the dependent. The results are undefined if this restriction is violated.
This example shows a general facility for encapsulating metaobjects before recording them as dependents. The facility defines a basic kind of encapsulating object: an updater. Specializations of the basic class can be defined with appropriate special updating behavior. In this way, information about the updating required is associated with each updater rather than with the metaobject being updated.
Updaters are used to encapsulate any metaobject which requires
updating when a given class or generic function is modified. The
function record-updater is called to both create an
updater and add it to the dependents of the class or generic function.
Methods on the generic function CLOS:UPDATE-DEPENDENT, specialized to the
specific class of updater do the appropriate update work.
(defclass updater ()
((dependent :initarg :dependent :reader dependent)))
(defun record-updater (class dependee dependent &REST initargs)
(let ((updater (apply #'make-instance class :dependent dependent
initargs)))
(add-dependent dependee updater)
updater))
A flush-cache-updater simply flushes the
cache of the dependent when it is updated.
(defclass flush-cache-updater (updater) ())
(defmethod update-dependent (dependee (updater flush-cache-updater) &REST args)
(declare (ignore args))
(flush-cache (dependent updater)))
CLOS:UPDATE-DEPENDENT(CLOS:UPDATE-DEPENDENT metaobject
dependent &REST initargs)
metaobjectdependentinitargsThis generic function is called to update a
dependent of metaobject.
When a class or a generic function is reinitialized each of
its dependents is updated. The initargs argument to
CLOS:UPDATE-DEPENDENT is the set of initialization arguments received by
REINITIALIZE-INSTANCE.
When a method is added to a generic function, each of the
generic function's dependents is updated. The initargs argument
is a list of two elements: the symbol ADD-METHOD, and the method
that was added.
When a method is removed from a generic function, each of the
generic function's dependents is updated. The initargs argument
is a list of two elements: the symbol REMOVE-METHOD, and the method
that was removed.
In each case, CLOS:MAP-DEPENDENTS is used to call
CLOS:UPDATE-DEPENDENT on each of the dependents. So, for example, the
update of a generic function's dependents when a method is added
could be performed by the following code:
(CLOS:MAP-DEPENDENTSgeneric-function#'(lambda (dep) (CLOS:UPDATE-DEPENDENTgeneric-functiondep 'add-method new-method)))
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
CLOS:ADD-DEPENDENT(CLOS:ADD-DEPENDENT metaobject
dependent)metaobjectdependentThis generic function adds dependent to the
dependents of metaobject. If dependent is already in the set
of dependents it is not added again (no ERROR is SIGNALed).
The generic function CLOS:MAP-DEPENDENTS can be called to access
the set of dependents of a class or generic function. The generic
function CLOS:REMOVE-DEPENDENT can be called to remove an object from
the set of dependents of a class or generic function. The effect of
calling CLOS:ADD-DEPENDENT or CLOS:REMOVE-DEPENDENT while a call to
CLOS:MAP-DEPENDENTS on the same class or generic function is in progress
is unspecified.
The situations in which CLOS:ADD-DEPENDENT is called are not
specified.
Methods
(CLOS:ADD-DEPENDENT
(class STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:ADD-DEPENDENT
(class CLOS:FUNCALLABLE-STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:ADD-DEPENDENT
(generic-function STANDARD-GENERIC-FUNCTION) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
CLOS:REMOVE-DEPENDENT(CLOS:REMOVE-DEPENDENT metaobject
dependent)metaobjectdependentThis generic function removes dependent from the
dependents of metaobject. If dependent is not one of the
dependents of metaobject, no ERROR is SIGNALed.
The generic function CLOS:MAP-DEPENDENTS can be called to access
the set of dependents of a class or generic function. The generic
function CLOS:ADD-DEPENDENT can be called to add an object from the set
of dependents of a class or generic function. The effect of calling
CLOS:ADD-DEPENDENT or CLOS:REMOVE-DEPENDENT while a call to
CLOS:MAP-DEPENDENTS on the same class or generic function is in progress
is unspecified.
The situations in which CLOS:REMOVE-DEPENDENT is called are not
specified.
Methods
(CLOS:REMOVE-DEPENDENT
(class STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:REMOVE-DEPENDENT
(class CLOS:FUNCALLABLE-STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:REMOVE-DEPENDENT
(class STANDARD-GENERIC-FUNCTION) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
CLOS:MAP-DEPENDENTS(CLOS:MAP-DEPENDENTS metaobject
function)metaobjectfunctionfunction to each of
the dependents of metaobject. The order in which the dependents
are processed is not specified, but function is applied to each
dependent once and only once. If, during the mapping,
CLOS:ADD-DEPENDENT or CLOS:REMOVE-DEPENDENT is called to alter the
dependents of metaobject, it is not specified whether the newly
added or removed dependent will have function applied to it.
Methods
(CLOS:MAP-DEPENDENTS
(metaobject STANDARD-CLASS) function)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:MAP-DEPENDENTS
(metaobject CLOS:FUNCALLABLE-STANDARD-CLASS) function)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:MAP-DEPENDENTS
(metaobject STANDARD-GENERIC-FUNCTION) function)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
This section lists the differences between the [AMOP] and the CLISP implementation thereof.
Not implemented in CLISP
The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented.
See Section 29.5.3.2, “Generic Function Invocation Protocol”.
Features implemented differently in CLISP
The class precedence list of CLOS:FUNCALLABLE-STANDARD-OBJECT
is different. See Section 29.2.2, “Inheritance Structure of Metaobject Classes”.
The DEFCLASS macro passes default values to CLOS:ENSURE-CLASS.
See Section 29.3.1, “Macro DEFCLASS”.
The DEFGENERIC macro passes default values to ENSURE-GENERIC-FUNCTION.
See Section 29.5.3.1, “Macro DEFGENERIC”.
The class CLOS:FORWARD-REFERENCED-CLASS is implemented differently.
See Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP.
The function CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER SIGNALs an ERROR
if the generic function has no lambda list.
Extensions specific to CLISP
The Meta-Object Protocol is applicable to classes of type STRUCTURE-CLASS.
The default superclass for STRUCTURE-CLASS instances is
STRUCTURE-OBJECT.
Structure classes do not support multiple inheritance and reinitialization.
See Section 29.3.5.1, “Initialization of class metaobjects”.
See also Section 8.2, “The structure Meta-Object Protocol”.
The DEFGENERIC macro supports user-defined options.
See User-defined options.
The class METHOD is subclassable.
See Section 29.2.2, “Inheritance Structure of Metaobject Classes”.
Slot names like NIL and T are allowed.
See Section 29.4.2.1.1, “Generic Function CLOS:SLOT-DEFINITION-NAME”.
The CLOS:VALIDATE-SUPERCLASS method is more permissive by
default and does not need to be overridden in
some “obvious” cases.
See Section 29.3.6.7, “Generic Function CLOS:VALIDATE-SUPERCLASS”.
New generic function CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS. It can sometimes
be used when overriding CLOS:DIRECT-SLOT-DEFINITION-CLASS is cumbersome.
New generic function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS. It can sometimes
be used when overriding CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS is cumbersome.
New function CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION. It
can be used in overriding methods of CLOS:COMPUTE-DISCRIMINATING-FUNCTION.
The generic function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS accepts a
:DECLARE keyword.
The functions CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS and
CLOS:STANDARD-INSTANCE-ACCESS support non-updated obsolete instances and
also support slots with allocation :CLASS.
The existence of the function CLOS:CLASS-DIRECT-SUBCLASSES
does not prevent otherwise unreferenced classes from being garbage-collected.
When CLISP encounters suspicious CLOS code, it issues a
WARNING of type CLOS:CLOS-WARNING.
To suppress the undesired warnings (not recommended!) use
EXT:SET-GLOBAL-HANDLER with MUFFLE-WARNING on the appropriate
WARNING type;.
To find where the warnings come from (recommended), set
*BREAK-ON-SIGNALS* to the appropriate WARNING type.
This is a hint that the order in which program files are loaded (order of definitions, order of macro expansions, or similar) is wrong. Example:
(defclass ware () ((title :initarg :title :accessor title)))
(defclass book (ware) ())
(defclass compact-disk (ware) ())
(defclass dvd (ware) ())
(defgeneric add-to-inventory (object))
(defmethod add-to-inventory ((object ware)) nil)
(add-to-inventory (make-instance 'book :title "CLtL1"))
(defvar *book-counter* 0)
(defmethod add-to-inventory ((object book)) (incf *book-counter*))
(add-to-inventory (make-instance 'book :title "CLtL2"))
*book-counter*
⇒ 1
Since [CLtL1] and [CLtL2] were already added to the inventory, the
programmer might have expected that *book-counter*
is 2.
A few functions, such as PRINT-OBJECT, are listed in the
[ANSI CL standard] and the [AMOP] as “standard generic functions”,
to which users may add methods.
This warning is not issued for such functions.
A generic function is defined by a contract.
Whoever puts a method on a generic function, however, is also
expecting a contract to be fulfilled.
(In the example above, it is that *book-counter*
equals the number of invocations
of add-to-inventory on book instances.)
If the generic function was already called before the
method was installed, the method's contract was definitely broken.
Maybe the programmer has foreseen this case (in this example:
he could initialize *book-counter* to the number of
instances of book that exist at this moment, rather than to 0),
or maybe not. This is what the warning is about.
This is a hint that different parts of the program, possibly developed by independent people, are colliding. Example: in addition to the code above:
(defvar *book-sales-statistics* (make-hash-table :test 'equal)) (defmethod add-to-inventory ((object book)) (setf (gethash (title object) sale-stats) (cons 0 0))) (add-to-inventory (make-instance 'book :title "AMOP")) *book-counter* ⇒1*book-sales-statistics* ⇒#S(HASH-TABLE :TEST FASTHASH-EQUAL ("AMOP" . (0 . 0)))
The programmer who programmed the first
method expects that add-to-inventory@book*book-counter* will be incremented.
The programmer who programmed the second
method expects that add-to-inventory@book*book-sales-statistics* gets
augmented. If the implementation gives no warning, one of the two
programmers will waste time debugging.
This warning can be warranted for the same reason as above: if the old method and the new method have a different contract, something is fishy and possibly wrong. Additionally, the programmers may not even have intended to replace the method. They may have intended cumulative effects of the two methods.
Table of Contents
This interface permits the definition of new classes of streams, and programming their behavior by defining methods for the elementary stream operations. It is based on the proposal STREAM-DEFINITION-BY-USER:GENERIC-FUNCTIONS of David N. Gray to X3J13 and is supported by most Common Lisp implementations currently in use.
All symbols defined by this interface, starting with the prefix
FUNDAMENTAL- or STREAM-,
are exported from the package “GRAY”
and EXT:RE-EXPORTed from “EXT”.
Defined classes
GRAY:FUNDAMENTAL-STREAMSTREAM and of STANDARD-OBJECT.
Its metaclass is STANDARD-CLASS.GRAY:FUNDAMENTAL-INPUT-STREAMSTREAMs.
It is a subclass of GRAY:FUNDAMENTAL-STREAM. The built-in function INPUT-STREAM-P
returns true on instances of this class. This means that when you
define a new stream class capable of doing input, you have to make it
a subclass of GRAY:FUNDAMENTAL-INPUT-STREAM.GRAY:FUNDAMENTAL-OUTPUT-STREAMSTREAMs.
It is a subclass of GRAY:FUNDAMENTAL-STREAM. The built-in function OUTPUT-STREAM-P
returns true on instances of this class. This means that when you
define a new stream class capable of doing output, you have to make
it a subclass of GRAY:FUNDAMENTAL-OUTPUT-STREAM.GRAY:FUNDAMENTAL-CHARACTER-STREAMSTREAM-ELEMENT-TYPE is CHARACTER. It is a subclass of
GRAY:FUNDAMENTAL-STREAM. It defines a method on STREAM-ELEMENT-TYPE that returns
CHARACTER.GRAY:FUNDAMENTAL-BINARY-STREAMSTREAM-ELEMENT-TYPE is a subtype of INTEGER. It is a
subclass of GRAY:FUNDAMENTAL-STREAM. When you define a subclass of GRAY:FUNDAMENTAL-BINARY-STREAM,
you have to provide a method on STREAM-ELEMENT-TYPE.
GRAY:FUNDAMENTAL-CHARACTER-INPUT-STREAMGRAY:FUNDAMENTAL-CHARACTER-STREAM and GRAY:FUNDAMENTAL-INPUT-STREAM.GRAY:FUNDAMENTAL-CHARACTER-OUTPUT-STREAMGRAY:FUNDAMENTAL-CHARACTER-STREAM and GRAY:FUNDAMENTAL-OUTPUT-STREAM.GRAY:FUNDAMENTAL-BINARY-INPUT-STREAMGRAY:FUNDAMENTAL-BINARY-STREAM and GRAY:FUNDAMENTAL-INPUT-STREAM.GRAY:FUNDAMENTAL-BINARY-OUTPUT-STREAMGRAY:FUNDAMENTAL-BINARY-STREAM and GRAY:FUNDAMENTAL-OUTPUT-STREAM.General generic functions defined on streams
(STREAM-ELEMENT-TYPE stream)Returns the stream's element type, normally a
subtype of CHARACTER or INTEGER.
The method for GRAY:FUNDAMENTAL-CHARACTER-STREAM returns CHARACTER.
((SETF STREAM-ELEMENT-TYPE)
new-element-type stream)Changes the stream's element type.
The default method SIGNALs an ERROR.
This function is a CLISP extension (see Section 21.8, “Function STREAM-ELEMENT-TYPE”).
(CLOSE stream &KEY
:ABORT)Closes the stream and flushes any associated buffers.
When you define a primary method on this
function, do not forget to CALL-NEXT-METHOD.
(OPEN-STREAM-P stream)Returns true before the stream has been closed, and
NIL after the stream has been closed.
You do not need to add methods to this function.
(GRAY:STREAM-POSITION
stream position)Just like FILE-POSITION, but NIL
position means inquire.
You must define a method for this function.
(GRAY:STREAM-READ-SEQUENCE
sequence stream &KEY :START :END)Used by READ-SEQUENCE. Deprecated.
Define GRAY:STREAM-READ-CHAR-SEQUENCE or GRAY:STREAM-READ-BYTE-SEQUENCE and call EXT:READ-CHAR-SEQUENCE/EXT:READ-BYTE-SEQUENCE instead.
The default method calls GRAY:STREAM-READ-CHAR-SEQUENCE or GRAY:STREAM-READ-BYTE-SEQUENCE.
(GRAY:STREAM-WRITE-SEQUENCE
sequence stream &KEY :START :END)Used by WRITE-SEQUENCE. Deprecated.
Define GRAY:STREAM-WRITE-CHAR-SEQUENCE or GRAY:STREAM-WRITE-BYTE-SEQUENCE and call EXT:WRITE-CHAR-SEQUENCE/EXT:WRITE-BYTE-SEQUENCE instead.
The default method calls GRAY:STREAM-WRITE-CHAR-SEQUENCE or GRAY:STREAM-WRITE-BYTE-SEQUENCE.
Generic functions for character input
(GRAY:STREAM-READ-CHAR stream)If a character was pushed back using GRAY:STREAM-UNREAD-CHAR,
returns and consumes it. Otherwise returns and consumes the next
character from the stream. Returns :EOF if the end-of-stream is reached.
You must define a method for this function.
(GRAY:STREAM-UNREAD-CHAR stream char)Pushes char, which must be the last character
read from the stream, back onto the front of the stream.
You must define a method for this function.
(GRAY:STREAM-READ-CHAR-NO-HANG stream)Returns a character or :EOF, like GRAY:STREAM-READ-CHAR, if
that would return immediately. If GRAY:STREAM-READ-CHAR's value is not available
immediately, returns NIL instead of waiting.
The default method simply calls GRAY:STREAM-READ-CHAR; this is sufficient for streams
whose GRAY:STREAM-READ-CHAR method never blocks.
(GRAY:STREAM-PEEK-CHAR stream)If a character was pushed back using GRAY:STREAM-UNREAD-CHAR,
returns it. Otherwise returns the next character from the stream,
avoiding any side effects GRAY:STREAM-READ-CHAR would do. Returns :EOF if the
end-of-stream is reached.
The default method calls GRAY:STREAM-READ-CHAR and GRAY:STREAM-UNREAD-CHAR; this is
sufficient for streams whose GRAY:STREAM-READ-CHAR method has no
side-effects.
(GRAY:STREAM-LISTEN stream)If a character was pushed back using GRAY:STREAM-UNREAD-CHAR,
returns it. Otherwise returns the next character from the stream, if
already available. If no character is available immediately, or if
end-of-stream is reached, returns NIL.
The default method calls GRAY:STREAM-READ-CHAR-NO-HANG and GRAY:STREAM-UNREAD-CHAR; this is
sufficient for streams whose GRAY:STREAM-READ-CHAR method has no
side-effects.
(GRAY:STREAM-READ-CHAR-WILL-HANG-P
stream)Returns NIL if GRAY:STREAM-READ-CHAR will return immediately.
Otherwise it returns true.
The default method calls GRAY:STREAM-READ-CHAR-NO-HANG and GRAY:STREAM-UNREAD-CHAR; this is
sufficient for streams whose GRAY:STREAM-READ-CHAR method has no side-effects.
This function is a CLISP extension (see EXT:READ-CHAR-WILL-HANG-P).
(GRAY:STREAM-READ-CHAR-SEQUENCE
stream sequence &OPTIONAL [start [end]])Fills the subsequence of sequence specified by
:START and :END with characters consecutively read from stream.
Returns the index of the first element of sequence that was not
updated (= end, or < end if the stream reached its end).
sequence is an ARRAY of CHARACTERs, i.e. a STRING.
start is a nonnegative INTEGER and defaults to 0.
end is a nonnegative INTEGER or NIL and defaults to NIL,
which stands for (.
LENGTH sequence)
The default method repeatedly calls GRAY:STREAM-READ-CHAR; this
is always sufficient if speed does not matter.
This function is a CLISP extension (see
EXT:READ-CHAR-SEQUENCE).
(GRAY:STREAM-READ-LINE stream)Reads a line of characters, and return two values:
the line (a STRING, without the terminating #\Newline character),
and a BOOLEAN value which is true if the line was terminated by
end-of-stream instead of #\Newline.
The default method repeatedly calls GRAY:STREAM-READ-CHAR; this
is always sufficient.
(GRAY:STREAM-CLEAR-INPUT stream)Clears all pending interactive input from the
stream, and returns true if some pending input was removed.
The default method does nothing and returns NIL; this is
sufficient for non-interactive streams.
Generic functions for character output
(GRAY:STREAM-WRITE-CHAR stream char)Writes char.
You must define a method for this function.
(GRAY:STREAM-LINE-COLUMN stream)Returns the column number where the next character
would be written (0 stands for the first column),
or NIL if that is not meaningful for this stream.
You must define a method for this function.
(GRAY:STREAM-START-LINE-P stream)Returns true if the next character would be written at the start of a new line.
The default method calls GRAY:STREAM-LINE-COLUMN and compares its result with
0; this is sufficient for streams whose GRAY:STREAM-LINE-COLUMN never returns NIL.
(GRAY:STREAM-WRITE-CHAR-SEQUENCE
stream sequence &OPTIONAL [start [end]])Outputs the subsequence of sequence specified
by :START and :END to stream.
sequence is an ARRAY of CHARACTERs, i.e. a STRING.
start is a nonnegative INTEGER and defaults to 0.
end is a nonnegative integer or NIL and defaults to NIL,
which stands for (.
LENGTH sequence)
The default method repeatedly calls GRAY:STREAM-WRITE-CHAR; this
is always sufficient if speed does not matter.
This function is a CLISP extension
(see EXT:WRITE-CHAR-SEQUENCE).
(GRAY:STREAM-WRITE-STRING
stream string &OPTIONAL [start [end]])Outputs the subsequence of string specified by
:START and :END to stream. Returns string.
string is a string. start is a nonnegative integer
and default to 0. end is a nonnegative integer or NIL and
defaults to NIL, which stands for (.
LENGTH string)
The default method calls GRAY:STREAM-WRITE-CHAR-SEQUENCE;
this is always sufficient.
(GRAY:STREAM-TERPRI stream)Outputs a #\Newline character.
The default method calls GRAY:STREAM-WRITE-CHAR; this is always
sufficient.
(GRAY:STREAM-FRESH-LINE stream)Possibly outputs a #\Newline character, so as to ensure that the next character would be written at the start of a new line. Returns true if it did output a #\Newline character.
The default method calls
GRAY:STREAM-START-LINE-P and then
GRAY:STREAM-TERPRI if necessary; this is always
sufficient.
(GRAY:STREAM-FINISH-OUTPUT stream)Ensures that any buffered output has reached its destination, and then returns.
The default method does nothing.
(GRAY:STREAM-FORCE-OUTPUT stream)Brings any buffered output on its way towards its destination, and returns without waiting until it has reached its destination.
The default method does nothing.
(GRAY:STREAM-CLEAR-OUTPUT stream)Attempts to discard any buffered output which has not yet reached its destination.
The default method does nothing.
(GRAY:STREAM-ADVANCE-TO-COLUMN
stream column)Ensures that the next character will be written at
least at column.
The default method outputs an appropriate amount of space characters; this is sufficient for non-proportional output.
Generic functions for binary input
(GRAY:STREAM-READ-BYTE stream)Returns and consumes the next integer from the
stream. Returns :EOF if the end-of-stream is reached.
You must define a method for this function.
(GRAY:STREAM-READ-BYTE-LOOKAHEAD stream)To be called only if stream's
STREAM-ELEMENT-TYPE is ( or UNSIGNED-BYTE 8)(.
Returns SIGNED-BYTE 8)T if GRAY:STREAM-READ-BYTE would return immediately with an
INTEGER result. Returns :EOF if the end-of-stream is already
known to be reached. If GRAY:STREAM-READ-BYTE's value is not available
immediately, returns NIL instead of waiting.
You must define a method for this function.
This function is a CLISP extension (see
EXT:READ-BYTE-LOOKAHEAD).
(GRAY:STREAM-READ-BYTE-WILL-HANG-P stream)To be called only if stream's
STREAM-ELEMENT-TYPE is ( or UNSIGNED-BYTE 8)(.
Returns SIGNED-BYTE 8)NIL if GRAY:STREAM-READ-BYTE will return immediately.
Otherwise it returns true.
The default method calls GRAY:STREAM-READ-BYTE-LOOKAHEAD; this is always sufficient.
This function is a CLISP extension (see EXT:READ-BYTE-WILL-HANG-P).
(GRAY:STREAM-READ-BYTE-NO-HANG stream)To be called only if stream's
STREAM-ELEMENT-TYPE is ( or UNSIGNED-BYTE 8)(.
Returns an SIGNED-BYTE 8)INTEGER or :EOF, like GRAY:STREAM-READ-BYTE, if that would
return immediately. If GRAY:STREAM-READ-BYTE's value is not available immediately,
returns NIL instead of waiting.
The default method calls GRAY:STREAM-READ-BYTE if GRAY:STREAM-READ-BYTE-LOOKAHEAD returns true;
this is always sufficient.
This function is a CLISP extension (see EXT:READ-BYTE-NO-HANG).
(GRAY:STREAM-READ-BYTE-SEQUENCE
stream sequence &OPTIONAL
[start [end [no-hang [interactive]]]])Fills the subsequence of sequence specified by
:START and :END with integers consecutively read from stream.
Returns the index of the first element of sequence that was not
updated (= end, or < end if the stream reached its end).
sequence is an ARRAY of INTEGERs.
start is a nonnegative INTEGER and defaults to 0.
end is a nonnegative INTEGER or NIL and defaults to NIL,
which stands for (.
If LENGTH sequence)no-hang is true, the function should avoid blocking and instead fill
only as many elements as are immediately available. If no-hang is false
and interactive is true, the function can block for reading the first
byte but should avoid blocking for any further bytes.
The default method repeatedly calls GRAY:STREAM-READ-BYTE; this
is always sufficient if speed does not matter.
This function is a CLISP extension (see
EXT:READ-BYTE-SEQUENCE).
Generic functions for binary output
(GRAY:STREAM-WRITE-BYTE
stream integer)Writes integer.
You must define a method for this function.
(GRAY:STREAM-WRITE-BYTE-SEQUENCE
stream sequence &OPTIONAL
[start [end [no-hang [interactive]]]])Outputs the subsequence of sequence specified
by :START and :END to stream
sequence is an ARRAY of INTEGERs.
start is a nonnegative INTEGER and defaults to 0.
end is a nonnegative INTEGER or NIL and defaults to NIL,
which stands for (.
If LENGTH sequence)no-hang is true, the function should avoid blocking and instead output
only as many elements as it can immediately proceed. If no-hang is false
and interactive is true, the function can block for writing the first
byte but should avoid blocking for any further bytes.
The default method repeatedly calls
GRAY:STREAM-WRITE-BYTE; this is always
sufficient if speed does not matter.
This function is a CLISP extension (see
EXT:WRITE-BYTE-SEQUENCE).
EXT:FILL-STREAMList of Examples
As an example of the use of “GRAY” STREAMs, CLISP
offers an additional class, EXT:FILL-STREAM. An instance of this class
is a “formatting” STREAM, which makes the final
output to the underlying stream look neat: indented and filled.
An instance of EXT:FILL-STREAM is created like this:
(MAKE-INSTANCE'EXT:FILL-STREAM:streamstream[:text-indent symbol-or-number] [:sexp-indent symbol-or-number-or-function])
where
streamSTREAM where the output actually
goes.symbol-or-numberINTEGER text
indentation or the indentation itself (defaults to 0).
symbol-or-number-or-functionWhen FORMAT writes an S-expression to a
EXT:FILL-STREAM using ~S, and the expression's printed
representation does not fit on the current line, it is printed on
separate lines, ignoring the prescribed text indentation and
preserving spacing. When this argument is non-NIL, the
S-expression is indented by:
Defaults to CUSTOM:*FILL-INDENT-SEXP*, whose initial value is 1+.
Note that, due to buffering, one must call FORCE-OUTPUT
when done with the EXT:FILL-STREAM (and before changing the indent variable).
The former is done automatically by the macro
(with-fill-stream (fill target-stream ...) ...).
Example 30.1. Example of EXT:FILL-STREAM usage
(defvar *my-indent-level*)
(with-output-to-string (out)
(let ((*print-right-margin* 20)
(*print-pretty* t)
(*my-indent-level* 2))
(with-fill-stream (fill out :text-indent '*my-indent-level*)
(format fill "~%this is some long sentence which will be broken at spaces")
(force-output fill)
(let ((*my-indent-level* 5))
(format fill "~%and properly indented to the level specified by the ~S argument which can be a ~S or an ~S - cool!"
:TEXT-INDENT 'symbol 'integer)
(force-output fill))
(format fill "~%Don't forget to call ~S on it, and/or use ~S Pretty formatting of the S-expressions printed with ~~S is preserved: ~S"
'force-output 'with-fill-stream '(defun foo (x y z) (if x (+ y z) (* y z)))))))
⇒ "
this is some long
sentence which
will be broken at
spaces
and properly
indented to
the level
specified by
the
:TEXT-INDENT
argument which
can be a
SYMBOL or an
INTEGER -
cool!
Don't forget to
call FORCE-OUTPUT
on it, and/or use
WITH-FILL-STREAM
Pretty formatting
of the
S-expressions
printed with ~S
is preserved:
(DEFUN FOO
(X Y Z)
(IF X (+ Y Z)
(* Y Z)))
"Table of Contents
EXT:ETHEEXT:LETF & EXT:LETF*EXT:MEMOIZEDEXT:WITH-COLLECTEXT:COMPILE-TIME-VALUEEXT:WITH-GENSYMSEXT:REMOVE-PLISTEXT:WITH-HTML-OUTPUT and EXT:WITH-HTTP-OUTPUTEXT:OPEN-HTTP and macro EXT:WITH-HTTP-INPUTCUSTOM:*HTTP-LOG-STREAM*EXT:BROWSE-URLCUSTOM:*HTTP-PROXY*EXT:CANONICALIZETable of Contents
EXT:ETHEEXT:LETF & EXT:LETF*EXT:MEMOIZEDEXT:WITH-COLLECTEXT:COMPILE-TIME-VALUEEXT:WITH-GENSYMSEXT:REMOVE-PLISTEXT:WITH-HTML-OUTPUT and EXT:WITH-HTTP-OUTPUTEXT:OPEN-HTTP and macro EXT:WITH-HTTP-INPUTCUSTOM:*HTTP-LOG-STREAM*EXT:BROWSE-URLCUSTOM:*HTTP-PROXY*EXT:CANONICALIZEParse command line arguments until the first
positional argument (see :SCRIPT in
Section 31.2, “Saving an Image”).
Load the memory image.
Install internal signal handlers.
Initialize time variables.
Initialize locale-dependent encodings.
Initialize stream variables.
Initialize pathname variables.
Initialize “FFI”.
Run all functions in CUSTOM:*INIT-HOOKS*.
Say “hi”, unless suppressed by -q.
Handle command line options: file loading and/or compilation, form evaluation, script execution, read-eval-print loop.
Unwind the STACK, executing cleanup forms in
UNWIND-PROTECT.
Run all functions in CUSTOM:*FINI-HOOKS*.
Call FRESH-LINE on the standard streams.
Say “bye” unless suppressed by -q.
Wait for a keypress if requested by
-w.
Close all open FILE-STREAMs.
Close all open DLLs.
CUSTOM:*INIT-HOOKS* is run like this:
(IGNORE-ERRORS(MAPC#'FUNCALLCUSTOM:*INIT-HOOKS*))
CUSTOM:*INIT-HOOKS* and init functionCUSTOM:*INIT-HOOKS* are
always run regardless of the command line
options before even the banner is printed.CUSTOM:*FINI-HOOKS* is run like this:
(MAPC#'FUNCALLCUSTOM:*FINI-HOOKS*)
The function (
saves the running CLISP's memory to the file EXT:SAVEINITMEM &OPTIONAL
(filename "lispinit.mem") &KEY :KEEP-GLOBAL-HANDLERS :QUIET
:INIT-FUNCTION :LOCKED-PACKAGES :START-PACKAGE :EXECUTABLE :NORC
:SCRIPT :DOCUMENTATION :VERBOSE)filename;
extension #P".mem" is recommended (when filename does not have an
extension, #P".mem" extension is automatically added unless the file
being created is an executable).
:QUIETIf this argument is not NIL, the startup banner
and the good-bye message will be suppressed, as if by -q.
This is not recommended for interactive application delivery, please append your banner to ours (using init function) instead of replacing it.
:VERBOSECUSTOM:*SAVEINITMEM-VERBOSE*; initial value is T.
:NORCNIL, the RC file
loading will be suppressed, as if by -norc.
:INIT-FUNCTIONThis argument specifies a function that will be
executed at startup of the saved image, before entering the standard read-eval-print loop
(but after all other initialization, see Section 31.1.1, “Cradle to Grave”);
thus, if you want to avoid the read-eval-print loop, you have to call EXT:EXIT at the
end of the init function yourself
(this does not prevent CUSTOM:*FINI-HOOKS* from being run).
See the manual for passing command line arguments to this function.
See also CUSTOM:*INIT-HOOKS* and CUSTOM:*FINI-HOOKS*.
:SCRIPTThis options determines the handling of positional arguments when the image is invoked.
T, then the first positional argument
is the script name and the rest is placed into EXT:*ARGS*, as described
in Section 32.6.2, “Scripting with CLISP”.NIL, then all positional arguments
are placed into EXT:*ARGS* to be handled by the init function.
This option defaults to T when init function is NIL and to
NIL when init function is non-NIL.
:DOCUMENTATIONThe description of what this image does, printed
by the -help-image olption.
Defaults to (DOCUMENTATION init function
'FUNCTION)
:LOCKED-PACKAGESCUSTOM:*SYSTEM-PACKAGE-LIST*.
:START-PACKAGE*PACKAGE* in the image being saved, and defaults to the current
value of *PACKAGE*.:KEEP-GLOBAL-HANDLERSWhen non-NIL, the currently established global
handlers (either with EXT:SET-GLOBAL-HANDLER or with -on-error)
are inherited by the image. Defaults to NIL, so that
$clisp -i myfile -x '(EXT:SAVEINITMEM)'
will produce an image without any global handlers inherited from the batch mode of the above command.
:EXECUTABLEWhen non-NIL, the saved file will be a
standalone executable.
In this case, the #P".mem" extension is not added.
On Win32 and Cygwin the extension #P".exe"
is added instead.
Additionally, if this argument is 0, the standard
CLISP command line options will not be processed by the
executable but will be placed into EXT:*ARGS* instead.
This is convenient for application delivery, so that your
CLISP-based application can accept, e.g., -x.
To override this feature of the image, you have to prefix the
options with "--clisp", e.g.,
use --clisp-x instead of -x.
This, given such a CLISP-based application, you can get to an
ordinary CLISP read-eval-print loop by doing
$application --clisp-x '(EXT:SAVEINITMEM"myclisp" :executable t :init-function nil)'$./myclisp [1]> (! 20) 2432902008176640000
These instructions are also printed by
--clisp--help.
Of course, this feature opens a security hole
if the application is running setuid root,
therefore CLISP resets the effective group and user IDs to the real
ones if it sees a "--clisp-*" option.
You can use this memory image with the -M option.
On UNIX systems, you may compress it with GNU gzip to save disk
space.
Memory images are not portable across different platforms
(in contrast with platform-independent #P".fas" files).
They are not even portable across linking sets: image saved using
the full linking set cannot be used with the base runtime:
$clisp -K full -x '(EXT:SAVEINITMEM)'$clisp -K base -M lispinit.mem base/lisp.run: initialization file `lispinit.mem' was not created by this version of CLISP runtime
See also SFmail/BF6EFF38DF3FA647BBD932720D8BED650BAA11%40parmbx02.ilog.biz/Gmane/devel/17757.
The functions
( |
(EXT:QUIT |
(EXT:BYE |
- all synonymous - terminate CLISP. If status is non-NIL,
CLISP aborts with the supplied numeric error status, i.e.,
the OS environment is informed that the CLISP session did not
succeed.
Final delimiters also terminate CLISP.
Glossary
CLISP is internationalized, and is localized for the languages English, German, French, Spanish, Dutch, Russian, and Danish. CLISP also supports internationalized Lisp programs, through GNU gettext, see Section 33.2, “Internationalization of User Programs”.
The facilities described in this section will work only for the languages for which CLISP itself is already localized.
The language CLISP uses to communicate with the user can be one of
ENGLISH |
DEUTSCH (i.e., German) |
FRANÇAIS (i.e., French) |
ESPAÑOL (i.e., Spanish) |
NEDERLANDS (i.e., Dutch) |
РУССКИЙ
(i.e. Russian) |
DANSK (i.e., Danish) |
This is controlled by the SYMBOL-MACRO
CUSTOM:*CURRENT-LANGUAGE*,
which can be set at run time as well as using the -L command line option.
If you wish to change the
locale directory
at run time too, you can do that by setting CUSTOM:*CURRENT-LANGUAGE* to a CONS
cell, whose CAR is the language (a SYMBOL, one of the above),
and whose CDR is the new locale directory.
More languages can be defined through the macro
I18N:DEFLANGUAGE:
(.
For such an additional language to take effect, you must install the
corresponding message catalog, or translate the messages yourself,
using GNU gettext and Emacs (or XEmacs)
po-mode.I18N:DEFLANGUAGE language)
This works only for strings. For arbitrary language-dependent
Lisp objects, you define one through the macro
I18N:DEFINTERNATIONAL:
( and add
language-dependent values through the macro
I18N:DEFINTERNATIONAL symbol &OPTIONAL
(default-language T))I18N:DEFLOCALIZED:
(
(One such form for each language. Languages without an assigned
value will be treated like the default-language.)
You can then access the localized value by calling
I18N:DEFLOCALIZED symbol language
value-form)I18N:LOCALIZED:
(I18N:LOCALIZED symbol &OPTIONAL language)
An “encoding” describes the correspondence
between CHARACTERs and raw bytes during input/output via
STREAMs with STREAM-ELEMENT-TYPE CHARACTER.
An EXT:ENCODING is an object composed of the following facets:
CHARACTERs that
can be represented and passed through the I/O channel, and the way
these characters translate into raw bytes, i.e., the map between
sequences of CHARACTER and (UNSIGNED-BYTE 8) in the form of STRINGs
and (VECTOR (UNSIGNED-BYTE 8)) as well as character and byte STREAMs.
In this context, for example, CHARSET:UTF-8 and CHARSET:UCS-4
are considered different, although they can represent the same set
of characters.EXT:ENCODINGs are also TYPEs. As such, they represent the set of
characters encodable in the character set. In this context, the way
characters are translated into raw bytes is ignored, and the line
terminator mode is ignored as well. TYPEP and SUBTYPEP can be used
on encodings:
(SUBTYPEPCHARSET:UTF-8CHARSET:UTF-16) ⇒; ⇒T(TSUBTYPEPCHARSET:UTF-16CHARSET:UTF-8) ⇒; ⇒T(TSUBTYPEPCHARSET:ASCII CHARSET:ISO-8859-1) ⇒; ⇒T(TSUBTYPEPCHARSET:ISO-8859-1 CHARSET:ASCII) ⇒; ⇒NILT
“1:1” encodings. Encodings which define a bijection between character and byte
sequences are called “1:1” encodings. CHARSET:ISO-8859-1 is an example of such an
encoding: any byte sequence corresponds to some character sequence and
vice versa. ASCII, however, is not a “1:1” encoding: there are no
characters for bytes in the range [128;255]. CHARSET:UTF-8 is not a
“1:1” encoding either: some byte sequences do not correspond to any character
sequence.
The following character sets are supported, as values of the corresponding (constant) symbol in the “CHARSET” package:
Symbols in package “CHARSET”
UCS-2
≡ UNICODE-16
≡ UNICODE-16-BIG-ENDIAN,
the 16-bit basic multilingual plane of the UNICODE character set.
Every character is represented as two bytes.UNICODE-16-LITTLE-ENDIAN
UCS-4
≡ UNICODE-32
≡ UNICODE-32-BIG-ENDIAN,
the 21-bit UNICODE character set. Every character is represented as
four bytes. This encoding is used by CLISP internally.UNICODE-32-LITTLE-ENDIANUTF-8,
the 21-bit UNICODE character set.
Every character is represented as one to four bytes.
ASCII characters represent themselves and need one byte per character.
Most Latin/Greek/Cyrillic/Hebrew characters need two bytes per
character. Most other characters need three bytes per character,
and the rarely used remaining characters need four bytes per
character. This is therefore, in general, the most space-efficient
encoding of all of Unicode.UTF-16,
the 21-bit UNICODE character set. Every character in the 16-bit
basic multilingual plane is represented as two bytes, and the
rarely used remaining characters need four bytes per character.
This character set is only available on
platforms with GNU libc or GNU libiconv.UTF-7,
the 21-bit UNICODE character set. This is a stateful 7-bit encoding.
Not all ASCII characters represent themselves.
This character set is only available on
platforms with GNU libc or GNU libiconv.JAVA,
the 21-bit UNICODE character set.
ASCII characters represent themselves and need one byte per character.
All other characters of the basic multilingual plane are represented
by \unnnn sequences
(nnnn a hexadecimal number)
and need 6 bytes per character. The remaining characters are represented
by \uxxxx\uyyyy
and need 12 bytes per character. While this encoding is very comfortable
for editing Unicode files using only ASCII-aware tools and editors, it
cannot faithfully represent all UNICODE text. Only text which
does not contain \u (backslash followed by
lowercase Latin u) can be faithfully represented by this encoding.
ASCII,
the well-known US-centric 7-bit character set (American Standard
Code for Information Interchange - ASCII).ISO-8859-1,
an extension of the ASCII character set, suitable for the Afrikaans, Albanian, Basque, Breton, Catalan,
Cornish, Danish, Dutch, English, Færoese, Finnish, French,
Frisian, Galician, German, Greenlandic, Icelandic, Irish, Italian,
Latin, Luxemburgish, Norwegian, Portuguese, Ræto-Romanic,
Scottish, Spanish, and Swedish languages.
This encoding has the nice property that
(LOOP:for i :from 0 :toCHAR-CODE-LIMIT:for c = (CODE-CHARi) :always (OR(NOT(TYPEPc CHARSET:ISO-8859-1)) (EQUALP(EXT:CONVERT-STRING-TO-BYTES(STRINGc) CHARSET:ISO-8859-1) (VECTORi)))) ⇒T
i.e., it is compatible with CLISP CODE-CHAR/CHAR-CODE
in its own domain.
ISO-8859-2,
an extension of the ASCII character set, suitable for the Croatian, Czech, German, Hungarian, Polish,
Slovak, Slovenian, and Sorbian languages. ISO-8859-3,
an extension of the ASCII character set, suitable for the Esperanto and Maltese languages.ISO-8859-4,
an extension of the ASCII character set, suitable for the Estonian, Latvian, Lithuanian and Sami (Lappish)
languages.ISO-8859-5,
an extension of the ASCII character set, suitable for the Bulgarian, Byelorussian, Macedonian, Russian,
Serbian, and Ukrainian languages.ISO-8859-6,
suitable for the Arabic language.ISO-8859-7,
an extension of the ASCII character set, suitable for the Greek language.ISO-8859-8,
an extension of the ASCII character set, suitable for the Hebrew language (without punctuation).ISO-8859-9,
an extension of the ASCII character set, suitable for the Turkish language.ISO-8859-10,
an extension of the ASCII character set, suitable for the Estonian, Icelandic, Inuit (Greenlandic), Latvian,
Lithuanian, and Sami (Lappish) languages.ISO-8859-13,
an extension of the ASCII character set, suitable for the Estonian, Latvian, Lithuanian, Polish and Sami
(Lappish) languages.ISO-8859-14,
an extension of the ASCII character set, suitable for the Irish Gælic, Manx Gælic, Scottish
Gælic, and Welsh languages.ISO-8859-15,
an extension of the ASCII character set, suitable for the ISO-8859-1 languages, with improvements for
French, Finnish and the Euro.ISO-8859-16
an extension of the ASCII character set, suitable for the Rumanian language.KOI8-R,
an extension of the ASCII character set, suitable for the Russian language (very popular, especially on the
internet).KOI8-U,
an extension of the ASCII character set, suitable for the Ukrainian language (very popular, especially on the
internet).KOI8-RU,
an extension of the ASCII character set, suitable for the Russian language. This character set is only available on
platforms with GNU libiconv.JIS_X0201,
a character set for the Japanese language.MAC-ARABIC,
a platform specific extension of the ASCII character set.MAC-CENTRAL-EUROPE,
a platform specific extension of the ASCII character set.MAC-CROATIAN,
a platform specific extension of the ASCII character set.MAC-CYRILLIC,
a platform specific extension of the ASCII character set.MAC-DINGBAT,
a platform specific character set.MAC-GREEK,
a platform specific extension of the ASCII character set.MAC-HEBREW,
a platform specific extension of the ASCII character set.MAC-ICELAND,
a platform specific extension of the ASCII character set.MAC-ROMAN
≡ MACINTOSH,
a platform specific extension of the ASCII character set.MAC-ROMANIA,
a platform specific extension of the ASCII character set.MAC-SYMBOL,
a platform specific character set.MAC-THAI,
a platform specific extension of the ASCII character set.MAC-TURKISH,
a platform specific extension of the ASCII character set.MAC-UKRAINE,
a platform specific extension of the ASCII character set.CP437, a DOS oldie,
a platform specific extension of the ASCII character set.CP437-IBM,
an IBM variant of CP437.CP737, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Greek language.CP775, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for some Baltic languages.CP850, a DOS oldie,
a platform specific extension of the ASCII character set.CP852, a DOS oldie,
a platform specific extension of the ASCII character set.CP852-IBM,
an IBM variant of CP852.CP855, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Russian language.CP857, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Turkish language.CP860, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Portuguese language.CP860-IBM,
an IBM variant of CP860.CP861, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Icelandic language.CP861-IBM,
an IBM variant of CP861.CP862, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Hebrew language.CP862-IBM,
an IBM variant of CP862.CP863, a DOS oldie,
a platform specific extension of the ASCII character set.CP863-IBM,
an IBM variant of CP863.CP864, a DOS oldie,
meant to be suitable for the Arabic language.CP864-IBM,
an IBM variant of CP864.
CP865, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for some Nordic languages.CP865-IBM,
an IBM variant of CP865.
CP866, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Russian language.CP869, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Greek language.CP869-IBM,
an IBM variant of CP869.
CP874, a DOS oldie,
a platform specific extension of the ASCII character set, meant to be suitable for the Thai language.CP874-IBM,
an IBM variant of CP874.
WINDOWS-1250
≡ CP1250,
a platform specific extension of the ASCII character set, heavily incompatible with ISO-8859-2.
WINDOWS-1251
≡ CP1251,
a platform specific extension of the ASCII character set, heavily incompatible with ISO-8859-5,
meant to be suitable for the Russian language.WINDOWS-1252
≡ CP1252,
a platform specific extension of the ISO-8859-1 character set.
WINDOWS-1253
≡ CP1253,
a platform specific extension of the ASCII character set, gratuitously incompatible with ISO-8859-7,
meant to be suitable for the Greek language.WINDOWS-1254
≡ CP1254,
a platform specific extension of the ISO-8859-9 character set.
WINDOWS-1255
≡ CP1255,
a platform specific extension of the ASCII character set, gratuitously incompatible with ISO-8859-8,
suitable for the Hebrew language.
This character set is only available on
platforms with GNU libc or GNU libiconv.WINDOWS-1256
≡ CP1256,
a platform specific extension of the ASCII character set, meant to be suitable for the Arabic language.WINDOWS-1257
≡ CP1257,
a platform specific extension of the ASCII character set.WINDOWS-1258
≡ CP1258, a platform specific extension of the ASCII character set, meant to be suitable for the
Vietnamese language. This character set is only available on
platforms with GNU libc or GNU libiconv.HP-ROMAN8,
a platform specific extension of the ASCII character set.NEXTSTEP,
a platform specific extension of the ASCII character set.EUC-JP,
a multibyte character set for the Japanese language.
This character set is only available on
platforms with GNU libc or GNU libiconv.SHIFT-JIS,
a multibyte character set for the Japanese language.
This character set is only available on
platforms with GNU libc or GNU libiconv.CP932,
a Microsoft variant of SHIFT-JIS.
This character set is only available on
platforms with GNU libc or GNU libiconv.ISO-2022-JP,
a stateful 7-bit multibyte character set for the Japanese language.
This character set is only available on
platforms with GNU libc or GNU libiconv.ISO-2022-JP-2,
a stateful 7-bit multibyte character set for the Japanese language.
This character set is only available on platforms with GNU libc 2.3
or newer or GNU libiconv.ISO-2022-JP-1,
a stateful 7-bit multibyte character set for the Japanese language.
This character set is only available on
platforms with GNU libiconv.EUC-CN,
a multibyte character set for simplified Chinese.
This character set is only available on
platforms with GNU libc or GNU libiconv.HZ,
a stateful 7-bit multibyte character set for simplified Chinese.
This character set is only available on
platforms with GNU libiconv.GBK,
a multibyte character set for Chinese,
This character set is only available on
platforms with GNU libc or GNU libiconv.CP936,
a Microsoft variant of GBK.
This character set is only available on
platforms with GNU libc or GNU libiconv.GB18030,
a multibyte character set for Chinese,
This character set is only available on
platforms with GNU libc or GNU libiconv.EUC-TW,
a multibyte character set for traditional Chinese.
This character set is only available on
platforms with GNU libc or GNU libiconv.BIG5,
a multibyte character set for traditional Chinese.
This character set is only available on
platforms with GNU libc or GNU libiconv.CP950,
a Microsoft variant of BIG5.
This character set is only available on
platforms with GNU libc or GNU libiconv.BIG5-HKSCS,
a multibyte character set for traditional Chinese.
This character set is only available on
platforms with GNU libc or GNU libiconv.ISO-2022-CN,
a stateful 7-bit multibyte character set for Chinese.
This character set is only available on
platforms with GNU libc or GNU libiconv.ISO-2022-CN-EXT,
a stateful 7-bit multibyte character set for Chinese.
This character set is only available on
platforms with GNU libc or GNU libiconv.EUC-KR,
a multibyte character set for Korean.
This character set is only available on
platforms with GNU libc or GNU libiconv.CP949,
a Microsoft variant of EUC-KR.
This character set is only available on
platforms with GNU libc or GNU libiconv.ISO-2022-KR,
a stateful 7-bit multibyte character set for Korean.
This character set is only available on
platforms with GNU libc or GNU libiconv.JOHAB,
a multibyte character set for Korean used mostly on DOS.
This character set is only available on
platforms with GNU libc or GNU libiconv.ARMSCII-8,
an extension of the ASCII character set, suitable for the Armenian. This character set is only available on
platforms with GNU libc or GNU libiconv.GEORGIAN-ACADEMY,
an extension of the ASCII character set, suitable for the Georgian. This character set is only available on
platforms with GNU libc or GNU libiconv.GEORGIAN-PS,
an extension of the ASCII character set, suitable for the Georgian. This character set is only available on
platforms with GNU libc or GNU libiconv.TIS-620,
an extension of the ASCII character set, suitable for the Thai. This character set is only available on
platforms with GNU libc or GNU libiconv.MULELAO-1,
an extension of the ASCII character set, suitable for the Laotian. This character set is only available on
platforms with GNU libiconv.CP1133,
an extension of the ASCII character set, suitable for the Laotian. This character set is only available on
platforms with GNU libc or GNU libiconv.VISCII,
an extension of the ASCII character set, suitable for the Vietnamese. This character set is only available on
platforms with GNU libc or GNU libiconv.TCVN,
an extension of the ASCII character set, suitable for the Vietnamese. This character set is only available on
platforms with GNU libc or GNU libiconv.BASE64, encodes
arbitrary byte sequences with 64 ASCII characters
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
as specifined by MIME; 3 bytes are encoded with 4
characters, line breaks are inserted after every 76 characters.
While this is not a traditional character set (i.e., it does
not map a set of characters in a natural language into bytes), it
does define a map between arbitrary byte sequences and certain
character sequences, so it falls naturally into the EXT:ENCODING class.
The character sets provided by the library function
iconv can also be used as encodings. To create such an encoding,
call EXT:MAKE-ENCODING with the character set name (a string) as the
:CHARSET argument.
When an EXT:ENCODING is available both as a built-in and
through iconv, the built-in is used, because it is more
efficient and available across all platforms.
These encodings are not assigned to global variables, since
there is no portable way to get the list of all character sets
supported by iconv.
On standard-compliant UNIX systems (e.g., GNU systems, such as GNU/Linux and GNU/Hurd) and on systems with GNU libiconv you get this list by calling the program: iconv -l.
The reason we use only GNU libc 2.2 or GNU libiconv is
that the other iconv implementations are broken in various ways and
we do not want to deal with random CLISP crashes caused by those bugs.
If your system supplies an iconv implementation which passes the
GNU libiconv's test suite, please report that
to clisp-list and a
future CLISP version will use iconv on your system.
The line terminator mode can be one of the following three keywords:
Windows programs typically use the :DOS line terminator,
sometimes they also accept :UNIX line terminators or produce
:MAC line terminators.
The HTTP protocol also requires :DOS line terminators.
The line terminator mode is relevant only for output (writing to a <