% -*- Mode: TeX -*- % Evaluation Control % Macros % Declarations % Introspection %-------------------- Lambda Expressions -------------------- %%% ========== LAMBDA (symbol) \begincom{lambda}\ftype{Symbol} \issue{DECLS-AND-DOC} \label Syntax:: \Defspec lambda {lambda-list {\DeclsAndDoc} \starparam{form}} \label Arguments:: \param{lambda-list}---an \term{ordinary lambda list}. \param{declaration}---a \misc{declare} \term{expression}; \noeval. \param{documentation}---a \term{string}; \noeval. \param{form}---a \term{form}. \label Description:: A \term{lambda expression} is a \term{list} that can be used in place of a \term{function name} in certain contexts to denote a \term{function} by directly describing its behavior rather than indirectly by referring to the name of an \term{established} \term{function}. \param{Documentation} is attached to the denoted \param{function} (if any is actually created) as a \term{documentation string}. \label See Also:: \specref{function}, \specref{documentation}, {\secref\LambdaExpressions}, {\secref\LambdaForms}, {\secref\DocVsDecls} \label Notes:: The \term{lambda form} \code ((lambda \param{lambda-list} . \param{body}) . \param{arguments}) \endcode is semantically equivalent to the \term{function form} \code (funcall #'(lambda \param{lambda-list} . \param{body}) . \param{arguments}) \endcode \endissue{DECLS-AND-DOC} \endcom%{lambda} %%% ========== LAMBDA (macro) \issue{ISO-COMPATIBILITY:ADD-SUBSTRATE} \begincom{lambda}\ftype{Macro} \label Syntax:: %% 7.6.0 7 \DefmacWithValues lambda {lambda-list {\DeclsAndDoc} \starparam{form}} {\param{function}} \label Arguments and Values:: \param{lambda-list}---an \term{ordinary lambda list}. \param{declaration}---a \misc{declare} \term{expression}; \noeval. \param{documentation}---a \term{string}; \noeval. \param{form}---a \term{form}. \param{function}---a \term{function}. \label Description:: Provides a shorthand notation for a \specref{function} \term{special form} involving a \term{lambda expression} such that: \code (lambda \param{lambda-list} {\DeclsAndDoc} \starparam{form}) \EQ (function (lambda \param{lambda-list} {\DeclsAndDoc} \starparam{form})) \EQ #'(lambda \param{lambda-list} {\DeclsAndDoc} \starparam{form}) \endcode \label Examples:: \code (funcall (lambda (x) (+ x 3)) 4) \EV 7 \endcode \label Side Effects:\None. \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \misc{lambda} (symbol) \label Notes:: This macro could be implemented by: \code (defmacro lambda (&whole form &rest bvl-decls-and-body) (declare (ignore bvl-decls-and-body)) `#',form) \endcode \endcom%{lambda} \endissue{ISO-COMPATIBILITY:ADD-SUBSTRATE} %-------------------- Evaluation Control -------------------- %%% ========== COMPILE \begincom{compile}\ftype{Function} \issue{FUNCTION-NAME:LARGE} %%\param{Name} has been changed to \param{function-name} throughout.} \endissue{FUNCTION-NAME:LARGE} \label Syntax:: \DefunWithValues compile {name {\opt} definition} {function, warnings-p, failure-p} \label Arguments and Values:: \param{name}---a \term{function name}, or \nil. %% 25.1.0 5 \param{definition}---a \term{lambda expression} or a \term{function}. \Default{the function definition of \param{name} if it names a \term{function}, or the \term{macro function} of \param{name} if it names a \term{macro}} The consequences are undefined if no \param{definition} is supplied when the \param{name} is \nil. %% 25.1.0 6 \param{function}---the \param{function-name}, \issue{COMPILED-FUNCTION-REQUIREMENTS:TIGHTEN} or a \term{compiled function}. \endissue{COMPILED-FUNCTION-REQUIREMENTS:TIGHTEN} \param{warnings-p}---a \term{generalized boolean}. \param{failure-p}---a \term{generalized boolean}. \label Description:: Compiles an \term{interpreted function}. %% Moon: Intent is compilation envirionment = startup environment. %% Just delete this phrase, I think. %in the current \term{dynamic environment}. \funref{compile} produces a \term{compiled function} from \param{definition}. If the \param{definition} is a \term{lambda expression}, it is coerced to a \term{function}. \issue{COMPILE-ARGUMENT-PROBLEMS-AGAIN:FIX} If the \param{definition} is already a \term{compiled function}, \funref{compile} either produces that function itself (\ie is an identity operation) or an equivalent function. \endissue{COMPILE-ARGUMENT-PROBLEMS-AGAIN:FIX} \editornote{KMP: There are a number of ambiguities here that still need resolution.}%!!! % Cases of interest: % Given: (defmacro foist (x) `(car ,x)) % What do these do: % (compile 'foist (macro-function 'foist)) % (compile 'foist (symbol-function 'foist)) % (compile 'foist '(lambda (x y) (+ x y))) If the \param{name} is \nil, the resulting \term{compiled function} is returned directly as the \term{primary value}. If a \term{non-nil} \param{name} is given, then the resulting \term{compiled function} replaces the existing \term{function} definition of \param{name} and the \param{name} is returned as the \term{primary value}; if \param{name} is a \term{symbol} that names a \term{macro}, its \term{macro function} is updated and the \param{name} is returned as the \term{primary value}. % I moved this paragraph so it isn't in the middle of the discussion % of compiler diagnostics. --sjl 7 Mar 92 \issue{QUOTE-SEMANTICS:NO-COPYING} % Constants -> Literal objects. -kmp 15-Jan-91 \term{Literal objects} appearing in code processed by the \funref{compile} function are neither copied nor \term{coalesced}. The code resulting from the execution of \funref{compile} references \term{objects} that are \funref{eql} to the corresponding \term{objects} in the source code. \endissue{QUOTE-SEMANTICS:NO-COPYING} \issue{COMPILER-DIAGNOSTICS:USE-HANDLER} \funref{compile} is permitted, but not required, to \term{establish} a \term{handler} for \term{conditions} \oftype{error}. For example, the \term{handler} might issue a warning and restart compilation from some \term{implementation-dependent} point in order to let the compilation proceed without manual intervention. \endissue{COMPILER-DIAGNOSTICS:USE-HANDLER} The \term{secondary value}, \param{warnings-p}, is \term{false} % clarify ``compiler diagnostics'' --sjl 7 Mar 92 %if no compiler diagnostics were issued, and \term{true} otherwise. if no \term{conditions} \oftype{error} or \typeref{warning} were detected by the compiler, and \term{true} otherwise. The \term{tertiary value}, \param{failure-p}, is \term{false} % clarify ``compiler diagnostics'' --sjl 7 Mar 92 %if no compiler diagnostics other than \term{style warnings} were issued. %A value of \term{true} indicates that there were serious compiler diagnostics %issued, or that other \term{conditions} \oftype{error} or \typeref{warning} %(but not \oftype{style-warning}) were signaled during compilation. if no \term{conditions} \oftype{error} or \typeref{warning} (other than \typeref{style-warning}) were detected by the compiler, and \term{true} otherwise. \label Examples:: \code (defun foo () "bar") \EV FOO (compiled-function-p #'foo) \EV \term{implementation-dependent} (compile 'foo) \EV FOO (compiled-function-p #'foo) \EV \term{true} (setf (symbol-function 'foo) (compile nil '(lambda () "replaced"))) \EV # (foo) \EV "replaced" \endcode % (defun foo ...) \EV foo ;A function definition. % (compile 'foo) \EV foo ;Compile it. % ;Now foo runs faster. \label Affected By:: \issue{COMPILER-WARNING-STREAM} \varref{*error-output*}, \endissue{COMPILER-WARNING-STREAM} \varref{*macroexpand-hook*}. The presence of macro definitions and proclamations. \label Exceptional Situations:: \issue{COMPILE-ARGUMENT-PROBLEMS-AGAIN:FIX} The consequences are undefined if the \term{lexical environment} surrounding the \term{function} to be compiled contains any \term{bindings} other than those for \term{macros}, \term{symbol macros}, or \term{declarations}. % The consequences are undefined if the \term{function} to be compiled % was defined in a \term{non-null lexical environment}. % The consequences are unspecified if the \term{function} is already a % \term{compiled function}. \endissue{COMPILE-ARGUMENT-PROBLEMS-AGAIN:FIX} %% should be an error signaled if name is nil and no definition is supplied. %% also if function is already compiled. %ERROR and WARNING conditions may be signaled within % COMPILE or COMPILE-FILE, including arbitrary errors which may % occur due to compile-time processing of (EVAL-WHEN (:COMPILE-TOPLEVEL) ...) % forms or macro expansion. % % The following information is mostly redundant with info in the chapter 3 % concept section, and contains some inconsistencies. Better to just % put in a cross-reference. --sjl 4 mar 92 % \issue{COMPILER-DIAGNOSTICS:USE-HANDLER} % The following list considers only % those conditions signaled by the compiler as % opposed to within the compiler. % % An error \oftype{error} might be signaled by the compiler in % situations where the compilation cannot proceed without % intervention. % Examples include % file open errors and % syntax errors. % % An error \oftype{warning} might be signaled by the compiler in % situations where the standard explicitly states % that a warning must, should, or might be signaled. % Also, an error \oftype{warning} might be signaled % by the compiler in situations where the compiler can determine % that a situation with undefined consequences or that would cause % an error to be signaled would result at runtime. % Examples include % violation of type declarations, % \term{assigning} or \term{binding} a \term{constant variable}, % calling a built-in Lisp function with the wrong number of arguments % or malformed keyword argument lists, % referencing a variable declared \declref{ignore}, % and the usage of unrecognized declaration specifiers. % % The compiler is permitted to signal errors \oftype{style-warning} % about matters of programming style. Although \term{style warnings} might % be signaled in these situations, no implementation is required to % signal them. However, if an implementation does choose to signal an % error about matters of programming style, % that error is \oftype{style-warning} and is signaled by a call to \funref{warn}. % Examples include % redefinition of a \term{function} with a different argument list, % calling a \term{function} with the wrong number of arguments, % \term{accessing} unreferenced local variables not declared \declref{ignore}, % and usage of declaration specifiers described in the standard but ignored by the compiler. % % \issue{COMPILER-WARNING-STREAM} % %%This is now implied by the remarks about using WARN above. % %\funref{compile} is permitted to issue warnings through \term{error output}. % \endissue{COMPILER-WARNING-STREAM} % % \endissue{COMPILER-DIAGNOSTICS:USE-HANDLER} For information about errors detected during the compilation process, \seesection\FileCompilerExceptions. \label See Also:: \funref{compile-file} \label Notes:\None. \endcom %%% ========== EVAL \begincom{eval}\ftype{Function} \label Syntax:: \DefunWithValues eval {form} {\starparam{result}} \label Arguments and Values:: \param{form}---a \term{form}. \param{results}---the \term{values} \term{yielded} by the \term{evaluation} of \param{form}. %% Goes without saying. -kmp 8-Aug-91 % %% 7.9.2 4 % Returns multiple values if \param{form} produces multiple values. \label Description:: %% 20.1.0 2 Evaluates \param{form} in the current \term{dynamic environment} and the \term{null lexical environment}. %% 20.1.0 1 \funref{eval} is a user interface to the evaluator. %% 8.2.0 5 The evaluator expands macro calls as if through the use of \funref{macroexpand-1}. %%% 9.1.0 3 %It is an error to attempt to evaluate a declaration. %Those \term{forms} that permit declarations to appear %perform explicit checks for their presence. \issue{QUOTE-SEMANTICS:NO-COPYING} Constants appearing in code processed by \funref{eval} are not copied nor coalesced. The code resulting from the execution of \funref{eval} references \term{objects} that are \funref{eql} to the corresponding \term{objects} in the source code. \endissue{QUOTE-SEMANTICS:NO-COPYING} %!!! Barmar: What about compiler macros? \label Examples:: \code (setq form '(1+ a) a 999) \EV 999 (eval form) \EV 1000 (eval 'form) \EV (1+ A) (let ((a '(this would break if eval used local value))) (eval form)) \EV 1000 \endcode \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \issue{EVALHOOK-STEP-CONFUSION:X3J13-NOV-89} %\funref{evalhook}, %\funref{applyhook}, \endissue{EVALHOOK-STEP-CONFUSION:X3J13-NOV-89} \funref{macroexpand-1}, {\secref\EvaluationModel} \label Notes:: %% 20.1.0 4 To obtain the current dynamic value of a \term{symbol}, use of \funref{symbol-value} is equivalent (and usually preferable) to use of \funref{eval}. %% 20.1.0 3 Note that an \funref{eval} \term{form} involves two levels of \term{evaluation} for its \term{argument}. First, \param{form} is \term{evaluated} by the normal argument evaluation mechanism as would occur with any \term{call}. The \term{object} that results from this normal \term{argument} \term{evaluation} becomes the \term{value} of the \param{form} \term{parameter}, and is then \term{evaluated} as part of the \funref{eval} \term{form}. For example: \code (eval (list 'cdr (car '((quote (a . b)) c)))) \EV b \endcode The \term{argument} \term{form} \f{(list 'cdr (car '((quote (a . b)) c)))} is evaluated in the usual way to produce the \term{argument} \f{(cdr (quote (a . b)))}; % this is then given to \funref{eval} % because \funref{eval} is being called explicitly, % and \funref{eval} then evaluates its \term{argument}, \f{(cdr (quote (a . b)))}, to produce \f{b}. Since a single \term{evaluation} already occurs for any \term{argument} \term{form} in any \term{function form}, \funref{eval} is sometimes said to perform ``an extra level of evaluation.'' \issue{EVALHOOK-STEP-CONFUSION:FIX} % Hooks are provided for user-supplied debugging routines % to obtain control during the execution of an interpretive evaluator. % \funref{evalhook} and \funref{applyhook} provide alternative % interfaces to the evaluator mechanism for use by these debugging routines. \endissue{EVALHOOK-STEP-CONFUSION:FIX} \endcom %%% ========== EVAL-WHEN \begincom{eval-when}\ftype{Special Operator} \label Syntax:: \DefspecWithValues eval-when {\paren{\starparam{situation}} \starparam{form}} {\starparam{result}} \label Arguments and Values:: \issue{EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS} \param{situation}---One of the \term{symbols} \kwd{compile-toplevel}\idxkwd{compile-toplevel}, \kwd{load-toplevel}\idxkwd{load-toplevel}, \kwd{execute}\idxkwd{execute}, \misc{compile}\idxref{compile}, \misc{load}\idxref{load}, or \misc{eval}\idxref{eval}. The use of \misc{eval}, \misc{compile}, and \misc{load} is deprecated. \issue{EVAL-WHEN-OBSOLETE-KEYWORDS:X3J13-MAR-1993} %They are supported when \specref{eval-when} is a \term{top level form}, %but their meaning is not defined elsewhere. \endissue{EVAL-WHEN-OBSOLETE-KEYWORDS:X3J13-MAR-1993} \endissue{EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS} \param{forms}---an \term{implicit progn}. \param{results}---the \term{values} of the \term{forms} if they are executed, or \nil\ if they are not. \label Description:: %%% 5.3.3 2 %\specref{eval-when} specifies when a particular body %of code is to be evaluated. %%% 5.3.3 1.5 %\specref{eval-when} allows pieces of code to %be executed only at compile time, only in compiled code, or %when interpreted but not compiled. %If no \param{forms} are executed, \specref{eval-when} returns %\nil. % %%% 5.3.3 3 %\f{eval} specifies that the interpreter should process the body. %\f{compile} specifies that the compiler should evaluate the body %at compile time in the compilation context. %\f{load} specifies that the compiler should arrange to evaluate %the forms in the body when the compiled file containing the %\specref{eval-when} form is \term{loaded}. % %The body of \specref{eval-when} is processed as an implicit %\specref{progn}, but only in the allowed \param{situations}. % % \issue{EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS} The body of an \specref{eval-when} form is processed as an \term{implicit progn}, but only in the \param{situations} listed. %Each \param{situation} must be a symbol, % either COMPILE, LOAD, or EVAL. % The file compilation section only describe processing by COMPILE-FILE. % We must say something explicit here about EVAL and COMPILE. % (The last paragraph from the eval-when cleanup has gotten lost.) % I have rewritten this below to include the missing info. --sjl 5 Mar 92 % The use of the \param{situations} \kwd{compile-toplevel} ({\tt compile}) and % \kwd{load-toplevel} ({\tt load}) controls whether and when processing % occurs for \term{top level forms}. The use of % the situation \kwd{execute} ({\tt eval}) controls whether % processing occurs for \term{non-top-level forms}. % % For a description of \specref{eval-when} processing, \seesection\FileCompilation. The use of the \param{situations} \kwd{compile-toplevel} (or {\tt compile}) and \kwd{load-toplevel} (or {\tt load}) controls whether and when \term{evaluation} occurs when \specref{eval-when} appears as a \term{top level form} in code processed by \funref{compile-file}. \Seesection\FileCompilation. The use of the \param{situation} \kwd{execute} (or {\tt eval}) controls whether evaluation occurs for other \specref{eval-when} \term{forms}; that is, those that are not \term{top level forms}, or those in code processed by \funref{eval} or \varref{compile}. If the \kwd{execute} situation is specified in such a \term{form}, then the body \param{forms} are processed as an \term{implicit progn}; otherwise, the \specref{eval-when} \term{form} returns \nil. % The \specref{eval-when} %construct can be more precisely understood in terms of % a model of how the file compiler, COMPILE-FILE, processes forms in a % file to be compiled. %When successive \term{forms} are %read from the file by \funref{compile-file}, %these \term{top level forms} are normally processed in % not-compile-time mode. There is one other mode, called % compile-time-too mode, that is also used for processing \term{top level forms}. % The \specref{eval-when} special form %is used to annotate a program % in a way that allows the program doing the processing to select % the appropriate mode. % %When \funref{compile-file} %encounters an \specref{eval-when} form, the \term{form} %is handled according to %the table in \thenextfigure. % %\boxfig %{\dimen0=.75pc %\tabskip \dimen0 plus .5 fil %\halign to \hsize {#\hfil\tabskip \dimen0 plus 1fil&#\hfil\tabskip %\dimen0 plus .5 fil&#\hfil\tabskip \dimen0 plus 1fil&#\hfil\tabskip \dimen0 plus 1fil %&#\hfil\cr %\noalign{\vskip -9pt} %\hfil{\bf A} & {\bf B} & {\bf C} & {\bf D}& {\bf Action} \cr %& & & & \cr % Yes & Yes &-- &-- &Process body in compile-time-too %mode\cr % No &Yes &Yes &Yes &Process body in compile-time-too mode\cr % No &Yes &Yes &No &Process body in not-compile-time mode\cr % No &Yes &No &-- &Process body in not-compile-time mode\cr % Yes &No &-- &-- &Evaluate body\cr % No &No &Yes &Yes &Evaluate body\cr % No &No &Yes &No &do nothing\cr % No &No &No &-- &do nothing\cr %\noalign{\vskip -9pt} %}} %\caption{\specref{eval-when} processing} %\endfig %Column A indicates %{\tt :compile-toplevel} processing. %Column B indicates \kwd{load-toplevel} processing. %Column C indicates {\tt :execute} processing. %Column D indicates compile-time-too processing. % % Process body means to process the body (using the procedure % outlined in this subsection) as an implicit toplevel \specref{progn}. % % % Evaluate body means to evaluate the body \param{forms} as an % \term{implicit progn} in the % % dynamic execution context % \term{dynamic environment} of the compiler and in the % \term{lexical environment} in which the \specref{eval-when} appears. % % For an \specref{eval-when} %form that is not a \term{top level form}, %if the \kwd{execute} situation is specified, %the body of the \specref{eval-when} %is treated as an \term{implicit progn}. Otherwise, the %\specref{eval-when} % form returns \nil. %An \specref{eval-when} form is a \term{non-top-level form} %if it is one of the following: %in the interpreter, in \funref{compile}, or in \funref{compile-file} %but not a \term{top level form}. \endissue{EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS} %!!! Barmar: Redundant. (KMP: I'll have to think about that.) \issue{DEFINING-MACROS-NON-TOP-LEVEL:ALLOW} \specref{eval-when} normally appears as a \term{top level form}, but it is meaningful for it to appear as a \term{non-top-level form}. However, the compile-time side effects described in {\secref\Compilation} only take place when \specref{eval-when} appears as a \term{top level form}. \endissue{DEFINING-MACROS-NON-TOP-LEVEL:ALLOW} %\specref{eval-when} is meaningful only as a \term{top level form}. \label Examples:: %!!! Are the EVAL-WHEN return values correct?? -kmp 29-Aug-91 %% Moon: Why isn't this compile toplevel? Maybe this example is not portable? %% It's an obfuscating example anyway. Delete it. % \code % (setq temp 3) \EV 3 % (eval-when (:compile-toplevel) (setq temp 2)) \EV NIL % temp \EV 3 % (eval-when (:execute) (setq temp 2)) \EV 2 % temp \EV 2 % \endcode %% 5.3.3 10 One example of the use of \specref{eval-when} is that for the compiler to be able to read a file properly when it uses user-defined \term{reader macros}, it is necessary to write \code (eval-when (:compile-toplevel :load-toplevel :execute) (set-macro-character #\\$ #'(lambda (stream char) (declare (ignore char)) (list 'dollar (read stream))))) \EV T \endcode This causes the call to \funref{set-macro-character} to be executed in the compiler's execution environment, thereby modifying its reader syntax table. \code ;;; The EVAL-WHEN in this case is not at toplevel, so only the :EXECUTE ;;; keyword is considered. At compile time, this has no effect. ;;; At load time (if the LET is at toplevel), or at execution time ;;; (if the LET is embedded in some other form which does not execute ;;; until later) this sets (SYMBOL-FUNCTION 'FOO1) to a function which ;;; returns 1. (let ((x 1)) (eval-when (:execute :load-toplevel :compile-toplevel) (setf (symbol-function 'foo1) #'(lambda () x)))) ;;; If this expression occurs at the toplevel of a file to be compiled, ;;; it has BOTH a compile time AND a load-time effect of setting ;;; (SYMBOL-FUNCTION 'FOO2) to a function which returns 2. (eval-when (:execute :load-toplevel :compile-toplevel) (let ((x 2)) (eval-when (:execute :load-toplevel :compile-toplevel) (setf (symbol-function 'foo2) #'(lambda () x))))) ;;; If this expression occurs at the toplevel of a file to be compiled, ;;; it has BOTH a compile time AND a load-time effect of setting the ;;; function cell of FOO3 to a function which returns 3. (eval-when (:execute :load-toplevel :compile-toplevel) (setf (symbol-function 'foo3) #'(lambda () 3))) ;;; #4: This always does nothing. It simply returns NIL. (eval-when (:compile-toplevel) (eval-when (:compile-toplevel) (print 'foo4))) ;;; If this form occurs at toplevel of a file to be compiled, FOO5 is ;;; printed at compile time. If this form occurs in a non-top-level ;;; position, nothing is printed at compile time. Regardless of context, ;;; nothing is ever printed at load time or execution time. (eval-when (:compile-toplevel) (eval-when (:execute) (print 'foo5))) ;;; If this form occurs at toplevel of a file to be compiled, FOO6 is ;;; printed at compile time. If this form occurs in a non-top-level ;;; position, nothing is printed at compile time. Regardless of context, ;;; nothing is ever printed at load time or execution time. (eval-when (:execute :load-toplevel) (eval-when (:compile-toplevel) (print 'foo6))) \endcode \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \funref{compile-file}, {\secref\Compilation} \label Notes:: \issue{EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS} The following effects are logical consequences of the definition of \specref{eval-when}: \beginlist \itemitem{\bull} Execution of a single \specref{eval-when} expression executes the body code at most once. \itemitem{\bull} \term{Macros} intended for use in \term{top level forms} should be written so that side-effects are done by the \term{forms} in the macro expansion. The macro-expander itself should not do the side-effects. For example: Wrong: \code (defmacro foo () (really-foo) `(really-foo)) \endcode Right: \code (defmacro foo () `(eval-when (:compile-toplevel :execute :load-toplevel) (really-foo))) \endcode Adherence to this convention means that such \term{macros} behave intuitively when appearing as \term{non-top-level forms}. \itemitem{\bull} Placing a variable binding around an \specref{eval-when} reliably captures the binding because the compile-time-too mode cannot occur (\ie introducing a variable binding means that the \specref{eval-when} is not a \term{top level form}). For example, \code (let ((x 3)) (eval-when (:execute :load-toplevel :compile-toplevel) (print x))) \endcode prints {\tt 3} at execution (\ie load) time, and does not print anything at compile time. This is important so that expansions of \macref{defun} and \macref{defmacro} can be done in terms of \specref{eval-when} and can correctly capture the \term{lexical environment}. \code (defun bar (x) (defun foo () (+ x 3))) \endcode might expand into \code (defun bar (x) (progn (eval-when (:compile-toplevel) (compiler::notice-function-definition 'foo '(x))) (eval-when (:execute :load-toplevel) (setf (symbol-function 'foo) #'(lambda () (+ x 3)))))) \endcode which would be treated by the above rules the same as \code (defun bar (x) (setf (symbol-function 'foo) #'(lambda () (+ x 3)))) \endcode when the definition of \f{bar} is not a \term{top level form}. \endlist \endissue{EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS} \endcom %% Replaced per X3J13. -kmp 05-Oct-93 % %%% ========== LOAD-TIME-VALUE % \begincom{load-time-value}\ftype{Special Operator} % \issue{LOAD-TIME-EVAL:R**3-NEW-SPECIAL-FORM} % % \label Syntax:: % % \DefspecWithValues load-time-value {form {\opt} read-only-p} {object} % % \label Arguments and Values:: % % \param{form}---a \term{form}; \evalspecial. % % \param{read-only-p}---one of the \term{symbols} \t\ or \nil; \noeval. % % \param{object}---the \term{primary value} resulting from evaluating \param{form}. % % \label Description:: % % \specref{load-time-value} provides a mechanism for delaying evaluation of \param{form} % until the expression is in the run-time environment; \seesection\Compilation. % % \param{Read-only-p} designates whether the result can be considered a % \term{constant object}. If \nil\ (the default), the result must be considered % ordinary, modifiable data. If \t, the result is a read-only quantity % that can, if appropriate to the \term{implementation}, % be copied into read-only space and/or \term{coalesced} with \term{similar} % \term{constant objects} from other \term{programs}. % % If a \specref{load-time-value} expression is processed by \funref{compile-file}, % the compiler performs its normal semantic processing (such as macro expansion % and translation into machine code) on \param{form}, but arranges for the % execution of \param{form} to occur at load time in a \term{null lexical environment}, % with the result of this \term{evaluation} then being treated as % %an immediate quantity % a \term{literal object} % at run time. It is guaranteed that the evaluation of \param{form} % will take place only once when the \term{file} is \term{loaded}, but % the order of evaluation with respect to the evaluation of % \term{top level forms} in the file is \term{implementation-dependent}. % \idxtext{order of evaluation}\idxtext{evaluation order} % % If a \specref{load-time-value} expression appears within a function compiled % with \funref{compile}, the \param{form} is evaluated at compile time in a % \term{null lexical environment}. The result of this compile-time evaluation % is treated as % %an immediate quantity % a \term{literal object} % in the compiled code. % % If a \specref{load-time-value} expression is processed by \funref{eval}, % \param{form} is evaluated in a \term{null lexical environment}, % and one value is returned. Implementations that implicitly compile % (or partially compile) expressions processed by \funref{eval} % %"can" => "might". Barrett thought "can" was clumsy. % might evaluate \param{form} only once, at the time this compilation is performed. % %This is intentionally similar to the % % freedom which implementations are given for the time of expanding % % macros in interpreted code. % % If the \term{same} \term{list} \f{(load-time-value \param{form})} is % evaluated or compiled more than once, it is \term{implementation-dependent} % whether \param{form} is evaluated only once or is evaluated more than once. % This can happen both when an expression being evaluated or compiled shares % substructure, and when the \term{same} \term{form} is processed by \funref{eval} or % \funref{compile} multiple times. % Since a \specref{load-time-value} expression can be % referenced in more than one place and can be evaluated multiple times % by \funref{eval}, it is % \term{implementation-dependent} whether each execution returns % a fresh \term{object} % or returns the same \term{object} as some other execution. % Users must use caution when destructively modifying the resulting % \term{object}. % % If two lists \f{(load-time-value \param{form})} % that are the \term{same} under \funref{equal} but are not \term{identical} % are evaluated or compiled, % their values always come from distinct evaluations of \param{form}. % %Per Barrett: "These forms" => "Their values" % Their \term{values} may not be coalesced % %Added per Barmar: % unless \param{read-only-p} is \t. % % \label Examples:\None. % % \label Affected By:\None. % % \label Exceptional Situations:\None. % % \label See Also:: % % \funref{compile-file}, % \funref{compile}, % \funref{eval}, % {\secref\MinimalCompilation}, % {\secref\Compilation} % % \label Notes:: % % \specref{load-time-value} must appear outside of quoted structure in a % ``for \term{evaluation}'' position. In situations which would appear to call % for use of \specref{load-time-value} within a quoted structure, % the \term{backquote} \term{reader macro} is probably called for; % \seesection\Backquote. % % \endissue{LOAD-TIME-EVAL:R**3-NEW-SPECIAL-FORM} % % \endcom %%% ========== LOAD-TIME-VALUE \begincom{load-time-value}\ftype{Special Operator} \issue{LOAD-TIME-EVAL:R**3-NEW-SPECIAL-FORM} \label Syntax:: \DefspecWithValues load-time-value {form {\opt} read-only-p} {object} \label Arguments and Values:: \param{form}---a \term{form}; \evalspecial. \param{read-only-p}---a \term{boolean}; \noeval. \param{object}---the \term{primary value} resulting from evaluating \param{form}. \label Description:: \specref{load-time-value} provides a mechanism for delaying evaluation of \param{form} until the expression is in the run-time environment; \seesection\Compilation. \param{Read-only-p} designates whether the result can be considered a \term{constant object}. If \t, the result is a read-only quantity that can, if appropriate to the \term{implementation}, be copied into read-only space and/or \term{coalesced} with \term{similar} \term{constant objects} from other \term{programs}. If \nil\ (the default), the result must be neither copied nor coalesced; it must be considered to be potentially modifiable data. If a \specref{load-time-value} expression is processed by \funref{compile-file}, the compiler performs its normal semantic processing (such as macro expansion and translation into machine code) on \param{form}, but arranges for the execution of \param{form} to occur at load time in a \term{null lexical environment}, with the result of this \term{evaluation} then being treated as %an immediate quantity a \term{literal object} at run time. It is guaranteed that the evaluation of \param{form} will take place only once when the \term{file} is \term{loaded}, but the order of evaluation with respect to the evaluation of \term{top level forms} in the file is \term{implementation-dependent}. \idxtext{order of evaluation}\idxtext{evaluation order} If a \specref{load-time-value} expression appears within a function compiled with \funref{compile}, the \param{form} is evaluated at compile time in a \term{null lexical environment}. The result of this compile-time evaluation is treated as %an immediate quantity a \term{literal object} in the compiled code. If a \specref{load-time-value} expression is processed by \funref{eval}, \param{form} is evaluated in a \term{null lexical environment}, and one value is returned. Implementations that implicitly compile (or partially compile) expressions processed by \funref{eval} %"can" => "might". Barrett thought "can" was clumsy. might evaluate \param{form} only once, at the time this compilation is performed. %This is intentionally similar to the % freedom which implementations are given for the time of expanding % macros in interpreted code. If the \term{same} \term{list} \f{(load-time-value \param{form})} is evaluated or compiled more than once, it is \term{implementation-dependent} whether \param{form} is evaluated only once or is evaluated more than once. This can happen both when an expression being evaluated or compiled shares substructure, and when the \term{same} \term{form} is processed by \funref{eval} or \funref{compile} multiple times. Since a \specref{load-time-value} expression can be referenced in more than one place and can be evaluated multiple times by \funref{eval}, it is \term{implementation-dependent} whether each execution returns a fresh \term{object} or returns the same \term{object} as some other execution. Users must use caution when destructively modifying the resulting \term{object}. If two lists \f{(load-time-value \param{form})} that are the \term{same} under \funref{equal} but are not \term{identical} are evaluated or compiled, their values always come from distinct evaluations of \param{form}. %Per Barrett: "These forms" => "Their values" Their \term{values} may not be coalesced %Added per Barmar: unless \param{read-only-p} is \t. \label Examples:: \code ;;; The function INCR1 always returns the same value, even in different images. ;;; The function INCR2 always returns the same value in a given image, ;;; but the value it returns might vary from image to image. (defun incr1 (x) (+ x #.(random 17))) (defun incr2 (x) (+ x (load-time-value (random 17)))) ;;; The function FOO1-REF references the nth element of the first of ;;; the *FOO-ARRAYS* that is available at load time. It is permissible for ;;; that array to be modified (e.g., by SET-FOO1-REF); FOO1-REF will see the ;;; updated values. (defvar *foo-arrays* (list (make-array 7) (make-array 8))) (defun foo1-ref (n) (aref (load-time-value (first *my-arrays*) nil) n)) (defun set-foo1-ref (n val) (setf (aref (load-time-value (first *my-arrays*) nil) n) val)) ;;; The function BAR1-REF references the nth element of the first of ;;; the *BAR-ARRAYS* that is available at load time. The programmer has ;;; promised that the array will be treated as read-only, so the system ;;; can copy or coalesce the array. (defvar *bar-arrays* (list (make-array 7) (make-array 8))) (defun bar1-ref (n) (aref (load-time-value (first *my-arrays*) t) n)) ;;; This use of LOAD-TIME-VALUE permits the indicated vector to be coalesced ;;; even though NIL was specified, because the object was already read-only ;;; when it was written as a literal vector rather than created by a constructor. ;;; User programs must treat the vector v as read-only. (defun baz-ref (n) (let ((v (load-time-value #(A B C) nil))) (values (svref v n) v))) ;;; This use of LOAD-TIME-VALUE permits the indicated vector to be coalesced ;;; even though NIL was specified in the outer situation because T was specified ;;; in the inner situation. User programs must treat the vector v as read-only. (defun baz-ref (n) (let ((v (load-time-value (load-time-value (vector 1 2 3) t) nil))) (values (svref v n) v))) \endcode \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \funref{compile-file}, \funref{compile}, \funref{eval}, {\secref\MinimalCompilation}, {\secref\Compilation} \label Notes:: \specref{load-time-value} must appear outside of quoted structure in a ``for \term{evaluation}'' position. In situations which would appear to call for use of \specref{load-time-value} within a quoted structure, the \term{backquote} \term{reader macro} is probably called for; \seesection\Backquote. Specifying \nil\ for \param{read-only-p} is not a way to force an object to become modifiable if it has already been made read-only. It is only a way to say that, for an object that is modifiable, this operation is not intended to make that object read-only. \endissue{LOAD-TIME-EVAL:R**3-NEW-SPECIAL-FORM} \endcom %%% ========== QUOTE \begincom{quote}\ftype{Special Operator} \label Syntax:: \DefspecWithValues quote {object} {object} \label Arguments and Values:: \param{object}---an \term{object}; \noeval. \label Description:: %% 7.1.1 3 \Thespecop{quote} just returns \param{object}. % added --sjl 3 Mar 92 The consequences are undefined if \term{literal objects} (including \term{quoted objects}) are destructively modified. \label Examples:: \code (setq a 1) \EV 1 (quote (setq a 3)) \EV (SETQ A 3) a \EV 1 'a \EV A ''a \EV (QUOTE A) '''a \EV (QUOTE (QUOTE A)) (setq a 43) \EV 43 (list a (cons a 3)) \EV (43 (43 . 3)) (list (quote a) (quote (cons a 3))) \EV (A (CONS A 3)) 1 \EV 1 '1 \EV 1 "foo" \EV "foo" '"foo" \EV "foo" (car '(a b)) \EV A '(car '(a b)) \EV (CAR (QUOTE (A B))) #(car '(a b)) \EV #(CAR (QUOTE (A B))) '#(car '(a b)) \EV #(CAR (QUOTE (A B))) \endcode \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: {\secref\Evaluation}, {\secref\QuoteMacro}, \issue{CONSTANT-MODIFICATION:DISALLOW} {\secref\ConstantModification} \endissue{CONSTANT-MODIFICATION:DISALLOW} \label Notes:: The textual notation \f{'\param{object}} is equivalent to \f{(quote \param{object})}; \seesection\ConstantModification. %% 7.1.0 1 Some \term{objects}, called \term{self-evaluating objects}, do not require quotation by \specref{quote}. However, \term{symbols} and \term{lists} are used to represent parts of programs, and so would not be useable as constant data in a program without \specref{quote}. Since \specref{quote} suppresses the \term{evaluation} of these \term{objects}, they become data rather than program. \endcom %-------------------- Macros -------------------- %%% ========== COMPILER-MACRO-FUNCTION \begincom{compiler-macro-function}\ftype{Accessor} \issue{DEFINE-COMPILER-MACRO:X3J13-NOV89} \label Syntax:: \DefunWithValues compiler-macro-function {name {\opt} environment} {function} \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \Defsetf compiler-macro-function {name {\opt} environment} {new-function} \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \label Arguments and Values:: \param{name}---a \term{function name}. \param{environment}---an \term{environment} \term{object}. \param{function}, \param{new-function}---a \term{compiler macro function}, or \nil. \label Description:: \term{Accesses} the \term{compiler macro function} named \param{name}, if any, in the \param{environment}. A value of \nil\ denotes the absence of a \term{compiler macro function} named \param{name}. \label Examples:\None. \label Affected By:\None. \label Exceptional Situations:: \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} The consequences are undefined if \param{environment} is \term{non-nil} in a use of \SETFof{compiler-macro-function}. \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \label See Also:: \macref{define-compiler-macro}, {\secref\CompilerMacros} \label Notes:\None. \endissue{DEFINE-COMPILER-MACRO:X3J13-NOV89} \endcom %%% ========== DEFINE-COMPILER-MACRO \begincom{define-compiler-macro}\ftype{Macro} \issue{DECLS-AND-DOC} \label Syntax:: \DefmacWithValuesNewline define-compiler-macro {name lambda-list {\DeclsAndDoc} \starparam{form}} {name} \label Arguments and Values:: \param{name}---a \term{function name}. % tweaked. --sjl 5 Mar 92 % \param{lambda-list}---a \term{lambda list}; % can contain the lambda list keywords % \keyref{allow-other-keys}, % \keyref{aux}, % \keyref{body}, % \keyref{environment}, % \keyref{key}, % \keyref{optional}, % \keyref{rest}, % and % \keyref{whole}. \param{lambda-list}---a \term{macro lambda list}. \param{declaration}---a \misc{declare} \term{expression}; \noeval. \param{documentation}---a \term{string}; \noeval. \param{form}---a \term{form}. \label Description:: \editornote{KMP: This definition probably needs to be fully expanded to not refer through the definition of defmacro, but should suffice for now.} % If this rewriting happens, be sure to copy the compile-time side-effects % info from DEFMACRO too. -- sjl 5 Mar 92 This is the normal mechanism for defining a \term{compiler macro function}. Its manner of definition is the same as for \macref{defmacro}; the only differences are: \beginlist \itemitem{\bull} The \param{name} can be a \term{function name} naming any \term{function} or \term{macro}. \itemitem{\bull} The expander function is installed as a \term{compiler macro function} for the \param{name}, rather than as a \term{macro function}. \itemitem{\bull} The \keyref{whole} argument is bound to the form argument that is passed to the \term{compiler macro function}. The remaining lambda-list parameters are specified as if this form contained the function name in the \term{car} and the actual arguments in the \term{cdr}, but if the \term{car} of the actual form is the symbol \funref{funcall}, then the destructuring of the arguments is actually performed using its \term{cddr} instead. \itemitem{\bull}\issue{DOCUMENTATION-FUNCTION-BUGS:FIX}% \param{Documentation} is attached as a \term{documentation string} to \param{name} (as kind \specref{compiler-macro}) and to the \term{compiler macro function}. \endissue{DOCUMENTATION-FUNCTION-BUGS:FIX} \itemitem{\bull} Unlike an ordinary \term{macro}, a \term{compiler macro} can decline to provide an expansion merely by returning a form that is the \term{same} as the original (which can be obtained by using \keyref{whole}). \endlist \label Examples:: \code (defun square (x) (expt x 2)) \EV SQUARE (define-compiler-macro square (&whole form arg) (if (atom arg) `(expt ,arg 2) (case (car arg) (square (if (= (length arg) 2) `(expt ,(nth 1 arg) 4) form)) (expt (if (= (length arg) 3) (if (numberp (nth 2 arg)) `(expt ,(nth 1 arg) ,(* 2 (nth 2 arg))) `(expt ,(nth 1 arg) (* 2 ,(nth 2 arg)))) form)) (otherwise `(expt ,arg 2))))) \EV SQUARE (square (square 3)) \EV 81 (macroexpand '(square x)) \EV (SQUARE X), \term{false} (funcall (compiler-macro-function 'square) '(square x) nil) \EV (EXPT X 2) (funcall (compiler-macro-function 'square) '(square (square x)) nil) \EV (EXPT X 4) (funcall (compiler-macro-function 'square) '(funcall #'square x) nil) \EV (EXPT X 2) (defun distance-positional (x1 y1 x2 y2) (sqrt (+ (expt (- x2 x1) 2) (expt (- y2 y1) 2)))) \EV DISTANCE-POSITIONAL (defun distance (&key (x1 0) (y1 0) (x2 x1) (y2 y1)) (distance-positional x1 y1 x2 y2)) \EV DISTANCE (define-compiler-macro distance (&whole form &rest key-value-pairs &key (x1 0 x1-p) (y1 0 y1-p) (x2 x1 x2-p) (y2 y1 y2-p) &allow-other-keys &environment env) (flet ((key (n) (nth (* n 2) key-value-pairs)) (arg (n) (nth (1+ (* n 2)) key-value-pairs)) (simplep (x) (let ((expanded-x (macroexpand x env))) (or (constantp expanded-x env) (symbolp expanded-x))))) (let ((n (/ (length key-value-pairs) 2))) (multiple-value-bind (x1s y1s x2s y2s others) (loop for (key) on key-value-pairs by #'cddr count (eq key ':x1) into x1s count (eq key ':y1) into y1s count (eq key ':x2) into x2s count (eq key ':y1) into y2s count (not (member key '(:x1 :x2 :y1 :y2))) into others finally (return (values x1s y1s x2s y2s others))) (cond ((and (= n 4) (eq (key 0) :x1) (eq (key 1) :y1) (eq (key 2) :x2) (eq (key 3) :y2)) `(distance-positional ,x1 ,y1 ,x2 ,y2)) ((and (if x1-p (and (= x1s 1) (simplep x1)) t) (if y1-p (and (= y1s 1) (simplep y1)) t) (if x2-p (and (= x2s 1) (simplep x2)) t) (if y2-p (and (= y2s 1) (simplep y2)) t) (zerop others)) `(distance-positional ,x1 ,y1 ,x2 ,y2)) ((and (< x1s 2) (< y1s 2) (< x2s 2) (< y2s 2) (zerop others)) (let ((temps (loop repeat n collect (gensym)))) `(let ,(loop for i below n collect (list (nth i temps) (arg i))) (distance ,@(loop for i below n append (list (key i) (nth i temps))))))) (t form)))))) \EV DISTANCE (dolist (form '((distance :x1 (setq x 7) :x2 (decf x) :y1 (decf x) :y2 (decf x)) (distance :x1 (setq x 7) :y1 (decf x) :x2 (decf x) :y2 (decf x)) (distance :x1 (setq x 7) :y1 (incf x)) (distance :x1 (setq x 7) :y1 (incf x) :x1 (incf x)) (distance :x1 a1 :y1 b1 :x2 a2 :y2 b2) (distance :x1 a1 :x2 a2 :y1 b1 :y2 b2) (distance :x1 a1 :y1 b1 :z1 c1 :x2 a2 :y2 b2 :z2 c2))) (print (funcall (compiler-macro-function 'distance) form nil))) \OUT (LET ((#:G6558 (SETQ X 7)) \OUT (#:G6559 (DECF X)) \OUT (#:G6560 (DECF X)) \OUT (#:G6561 (DECF X))) \OUT (DISTANCE :X1 #:G6558 :X2 #:G6559 :Y1 #:G6560 :Y2 #:G6561)) \OUT (DISTANCE-POSITIONAL (SETQ X 7) (DECF X) (DECF X) (DECF X)) \OUT (LET ((#:G6567 (SETQ X 7)) \OUT (#:G6568 (INCF X))) \OUT (DISTANCE :X1 #:G6567 :Y1 #:G6568)) \OUT (DISTANCE :X1 (SETQ X 7) :Y1 (INCF X) :X1 (INCF X)) \OUT (DISTANCE-POSITIONAL A1 B1 A2 B2) \OUT (DISTANCE-POSITIONAL A1 B1 A2 B2) \OUT (DISTANCE :X1 A1 :Y1 B1 :Z1 C1 :X2 A2 :Y2 B2 :Z2 C2) \EV NIL \endcode \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \funref{compiler-macro-function}, \macref{defmacro}, \funref{documentation}, {\secref\DocVsDecls} \label Notes:: The consequences of writing a \term{compiler macro} definition for a function in \thepackage{common-lisp} are undefined; it is quite possible that in some \term{implementations} such an attempt would override an equivalent or equally important definition. In general, it is recommended that a programmer only write \term{compiler macro} definitions for \term{functions} he or she personally maintains--writing a \term{compiler macro} definition for a function maintained elsewhere is normally considered a violation of traditional rules of modularity and data abstraction. \endissue{DECLS-AND-DOC} \endcom %%% ========== DEFMACRO \begincom{defmacro}\ftype{Macro} \issue{DECLS-AND-DOC} \label Syntax:: \DefmacWithValuesNewline defmacro {name lambda-list {\DeclsAndDoc} \starparam{form}} {name} \label Arguments and Values:: \param{name}---a \term{symbol}. %!!! maybe call it a "user symbol" ?? -kmp 2-Aug-91 %% 8.1.0 9 %% 8.1.0 10 %% 8.1.0 11 %% 8.1.0 12 \param{lambda-list}---a \term{macro lambda list}. \param{declaration}---a \misc{declare} \term{expression}; \noeval. \param{documentation}---a \term{string}; \noeval. \param{form}---a \term{form}. \label Description:: %% 8.1.0 6 Defines \param{name} as a \term{macro} by associating a \term{macro function} with that \param{name} in the global environment. \issue{DEFINING-MACROS-NON-TOP-LEVEL:ALLOW} % Reworded garbled text. --sjl 7 Mar 92 %When the \term{macro function} is called, %the \param{forms} are evaluated in %the \term{lexical environment} in which the \macref{defmacro} form was evaluated. The \term{macro function} is defined in the same \term{lexical environment} in which the \macref{defmacro} \term{form} appears. \endissue{DEFINING-MACROS-NON-TOP-LEVEL:ALLOW} %% 8.1.0 7 The parameter variables in \param{lambda-list} are bound to destructured portions of the macro call. The expansion function accepts two arguments, a \term{form} and an \term{environment}. The expansion function returns a \term{form}. The body of the expansion function is specified by \param{forms}. \param{Forms} are executed in order. The value of the last \param{form} executed is returned as the expansion of the \term{macro}. \issue{FLET-IMPLICIT-BLOCK:YES} \issue{DEFMACRO-BLOCK-SCOPE:EXCLUDES-BINDINGS} The body \param{forms} of the expansion function (but not the \param{lambda-list}) \endissue{DEFMACRO-BLOCK-SCOPE:EXCLUDES-BINDINGS} are implicitly enclosed in a \term{block} whose name is \param{name}. \endissue{FLET-IMPLICIT-BLOCK:YES} The \param{lambda-list} conforms to the requirements described in \secref\MacroLambdaLists. \issue{DOCUMENTATION-FUNCTION-BUGS:FIX} \param{Documentation} is attached as a \term{documentation string} to \param{name} (as kind \specref{function}) and to the \term{macro function}. \endissue{DOCUMENTATION-FUNCTION-BUGS:FIX} %% 8.1.0 17 \macref{defmacro} can be used to redefine a \term{macro} or to replace a \term{function} definition with a \term{macro} definition. %% sandra says this is redundant %The consequences are undefined if a \term{special form} is redefined %using \macref{defmacro}. \issue{RECURSIVE-DEFTYPE:EXPLICITLY-VAGUE} Recursive expansion of the \term{form} returned must terminate, including the expansion of other \term{macros} which are \term{subforms} of other \term{forms} returned. %% Per Moon#13 (first public review) -kmp 5-May-93 The consequences are undefined if the result of fully macroexpanding %a form contains any non-constant circular list structure. a \term{form} contains any \term{circular} \term{list structure} except in \term{literal objects}. \endissue{RECURSIVE-DEFTYPE:EXPLICITLY-VAGUE} \issue{COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY} % added qualification about top-level-ness --sjl 5 Mar 92 If a \macref{defmacro} \term{form} appears as a \term{top level form}, the \term{compiler} must store the \term{macro} definition at compile time, so that occurrences of the macro later on in the file can be expanded correctly. Users must ensure that the body of the \term{macro} can be evaluated at compile time if it is referenced within the \term{file} being \term{compiled}. \endissue{COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY} \label Examples:: \code (defmacro mac1 (a b) "Mac1 multiplies and adds" `(+ ,a (* ,b 3))) \EV MAC1 (mac1 4 5) \EV 19 (documentation 'mac1 'function) \EV "Mac1 multiplies and adds" (defmacro mac2 (&optional (a 2 b) (c 3 d) &rest x) `'(,a ,b ,c ,d ,x)) \EV MAC2 (mac2 6) \EV (6 T 3 NIL NIL) (mac2 6 3 8) \EV (6 T 3 T (8)) (defmacro mac3 (&whole r a &optional (b 3) &rest x &key c (d a)) `'(,r ,a ,b ,c ,d ,x)) \EV MAC3 (mac3 1 6 :d 8 :c 9 :d 10) \EV ((MAC3 1 6 :D 8 :C 9 :D 10) 1 6 9 8 (:D 8 :C 9 :D 10)) \endcode % (defmacro mac4 % (&whole (su &rest (p &rest q)) a % &optional (b 3) &rest x &key c (d a)) % `'(,su ,p ,a ,b ,c ,d ,x)) \EV MAC4 % (mac4 1 6 :d 8 :c 9 :d 10) \EV (MAC4 1 1 6 9 8 (:D 8 :C 9 :D 10)) %An example of destructuring follows: % %\code % (defmacro halibut ((mouth eye1 eye2) % ((fin1 length1) (fin2 length2)) % tail) % ...) %\endcode %Now consider this macro call: % %\code % (halibut (m (car eyes) (cdr eyes)) % ((f1 (count-scales f1)) (f2 (count-scales f2))) % my-favorite-tail) \EV NIL %\endcode %This would cause the expansion function to receive the %values in \thenextfigure\ for its parameters: % %\boxfig %{\dimen0=.75pc %\tabskip \dimen0 plus .5 fil %\halign to \hsize {#\hfil\tabskip \dimen0 plus 1fil&#\hfil\cr %\noalign{\vskip -9pt} %\hfil{{\sl Parameter\/}} & {{\sl Value\/}} \cr %\noalign{\vskip 2pt\hrule\vskip 2pt} %mouth & m \cr %eye1 & (car eyes) \cr %eye2 & (cdr eyes) \cr %fin1 & f1 \cr %length1 & (count-scales f1) \cr %fin2 & f2 \cr %length2 & (count-scales f2) \cr %tail & my-favorite-tail \cr %\noalign{\vskip -9pt} %}} %\caption{Destructuring example expansion function values} %\endfig %The following macro call would be in error because there would be no %argument form to match the parameter \f{length1}: % %\code % (halibut (m (car eyes) (cdr eyes)) % ((f1) (f2 (count-scales f2))) % my-favorite-tail) %\endcode %The following macro call would be in error because a \term{symbol} appears %in the call where the structure of the \term{lambda list} requires a %\term{list}: % %\code % (halibut my-favorite-head % ((f1 (count-scales f1)) (f2 (count-scales f2))) % my-favorite-tail) %\endcode %The fact that the value of the variable \f{my-favorite-head} %might happen to be a \term{list} is irrelevant here. It is the macro call %itself whose structure must match that of the \macref{defmacro} %\term{lambda list}. % %%% 8.1.0 25 %The use of \term{lambda list keywords} is illustrated as follows. %Suppose it is convenient within the expansion %function for \f{halibut} to be able to refer to the \term{list} %whose components are called \f{mouth}, \f{eye1}, and \f{eye2} %as \f{head}. %This may be written as follows: % %\code % (defmacro halibut ((&whole head mouth eye1 eye2) % ((fin1 length1) (fin2 length2)) % tail) % ...) %\endcode %Now consider the same valid macro call as before: % %\code % (halibut (m (car eyes) (cdr eyes)) % ((f1 (count-scales f1)) (f2 (count-scales f2))) % my-favorite-tail) \EV NIL %\endcode %This would cause the expansion function to receive the same %values for its parameters and also a value for the parameter \f{head} %as in \thenextfigure. % %\boxfig %{\dimen0=.75pc %\tabskip \dimen0 plus .5 fil %\halign to \hsize {#\hfil\tabskip \dimen0 plus 1fil&#\hfil\cr %\noalign{\vskip -9pt} %\hfil{{\sl Parameter\/}} & {{\sl Value\/}} \cr %\noalign{\vskip 2pt\hrule\vskip 2pt} %head & (m (car eyes) (cdr eyes)) \cr %\noalign{\vskip -9pt} %}} %\caption{Lambda list keywords expansion function values example} %\endfig % %%% 8.1.0 19 %The following implements a conditional \term{form} analogous to the %\fortran\ arithmetic IF statement. %The \term{form} should accept four argument forms: a \f{test-value}, %a \f{neg-form}, a \f{zero-form}, and a \f{pos-form}. %One of the last three forms is chosen to be executed according %to whether the value of the \f{test-form} is positive, negative, %or zero. %Using \macref{defmacro}, a definition for such a \term{form} %might look like this: % %\code % (defmacro arithmetic-if (test neg-form zero-form pos-form) % (let ((var (gensym))) % `(let ((,var ,test)) % (cond ((< ,var 0) ,neg-form) % ((= ,var 0) ,zero-form) % (t ,pos-form))))) \EV ARITHMETIC-IF %\endcode %Note the use of the backquote facility in this definition, %and also the use of \funref{gensym} to generate a new variable name. %This is necessary to avoid conflict with any variables that might %be referred to in \f{neg-form}, \f{zero-form}, or \f{pos-form}. % %%% 8.1.0 20 %If the form is executed by the interpreter, it will cause the %function definition of the symbol \f{arithmetic-if} %to be a macro associated with which is %a two-argument expansion function roughly equivalent to: % %\code % (lambda (calling-form environment) % (declare (ignore environment)) % (let ((var (gensym))) % (list 'let % (list (list 'var (cadr calling-form))) % (list 'cond % (list (list '< var '0) (caddr calling-form)) % (list (list '= var '0) (cadddr calling-form)) % (list 't (fifth calling-form)))))) %\endcode % Barmar had noted that if we were going to show the above lambda, we should show % the defmacro that might have produced it. But since we're not going to show it, % I guess the issue is moot. -kmp 28-Dec-90 % %%% 8.1.0 21 %The \term{lambda expression} %could have been produced by the \macref{defmacro} macro. %The calls to \funref{list} are the (hypothetical) result %of the backquote (\f{\bq}) %macro character and its associated commas. %The precise macro expansion function might depend on the implementation. %For example, the implementation %might provide some degree of explicit error checking on the number %of argument forms in the macro call. % %%% 8.1.0 22 % %%If \funref{eval} encounters %% %%\code % (arithmetic-if (- x 4.0) %% (- x) %% (error "Strange zero") %% x) %%\endcode %this will be expanded into something like % %\code % (let ((g407 (- x 4.0))) % (cond ((< g407 0) (- x)) % ((= g407 0) (error "Strange zero")) % (t x))) %\endcode %and \funref{eval} tries again on this new form. % %%% 8.1.0 23 %To expand on this example %the \f{pos-form} %and \f{zero-form} could be omitted, allowing their values to default to \nil, %in the same way that the \f{else} form of \specref{if} %may be omitted: % %\code % (defmacro arithmetic-if (test neg-form &optional zero-form pos-form) % (let ((var (gensym))) % \bq(let ((,var ,test)) % (cond ((< ,var 0) ,neg-form) % ((= ,var 0) ,zero-form) % (t ,pos-form))))) %\endcode %Then % %\code % (arithmetic-if (- x 4.0) (print x)) %\endcode %would be expanded into something like % %\code % (let ((g408 (- x 4.0))) % (cond ((< g408 0) (print x)) % ((= g408 0) nil) % (t nil))) %\endcode %% 8.1.0 26 The stipulation that an embedded \term{destructuring lambda list} is permitted only where \term{ordinary lambda list} syntax would permit a parameter name but not a \term{list} is made to prevent ambiguity. For example, the following is not valid: \code (defmacro loser (x &optional (a b &rest c) &rest z) ...) \endcode because \term{ordinary lambda list} syntax does permit a \term{list} following \optional; the list \f{(a b \&rest c)} would be interpreted as describing an optional parameter named \f{a} whose default value is that of the form \f{b}, with a supplied-p parameter named \keyref{rest} (not valid), and an extraneous symbol \f{c} in the list (also not valid). An almost correct way to express this is \code (defmacro loser (x &optional ((a b &rest c)) &rest z) ...) \endcode The extra set of parentheses removes the ambiguity. However, the definition is now incorrect because a macro call such as \f{(loser (car pool))} would not provide any argument form for the lambda list \f{(a b \&rest c)}, and so the default value against which to match the \term{lambda list} would be \nil\ because no explicit default value was specified. The consequences of this are unspecified since the empty list, \nil, does not have \term{forms} to satisfy the parameters \f{a} and \f{b}. The fully correct definition would be either \code (defmacro loser (x &optional ((a b &rest c) '(nil nil)) &rest z) ...) \endcode or \code (defmacro loser (x &optional ((&optional a b &rest c)) &rest z) ...) \endcode These differ slightly: the first requires that if the macro call specifies \f{a} explicitly then it must also specify \f{b} explicitly, whereas the second does not have this requirement. For example, \code (loser (car pool) ((+ x 1))) \endcode would be a valid call for the second definition but not for the first. \issue{DEFMACRO-LAMBDA-LIST:TIGHTEN-DESCRIPTION} \code (defmacro dm1a (&whole x) `',x) (macroexpand '(dm1a)) \EV (QUOTE (DM1A)) (macroexpand '(dm1a a)) is an error. (defmacro dm1b (&whole x a &optional b) `'(,x ,a ,b)) (macroexpand '(dm1b)) is an error. (macroexpand '(dm1b q)) \EV (QUOTE ((DM1B Q) Q NIL)) (macroexpand '(dm1b q r)) \EV (QUOTE ((DM1B Q R) Q R)) (macroexpand '(dm1b q r s)) is an error. \endcode \code (defmacro dm2a (&whole form a b) `'(form ,form a ,a b ,b)) (macroexpand '(dm2a x y)) \EV (QUOTE (FORM (DM2A X Y) A X B Y)) (dm2a x y) \EV (FORM (DM2A X Y) A X B Y) (defmacro dm2b (&whole form a (&whole b (c . d) &optional (e 5)) &body f &environment env) ``(,',form ,,a ,',b ,',(macroexpand c env) ,',d ,',e ,',f)) ;Note that because backquote is involved, implementations may differ ;slightly in the nature (though not the functionality) of the expansion. (macroexpand '(dm2b x1 (((incf x2) x3 x4)) x5 x6)) \EV (LIST* '(DM2B X1 (((INCF X2) X3 X4)) X5 X6) X1 '((((INCF X2) X3 X4)) (SETQ X2 (+ X2 1)) (X3 X4) 5 (X5 X6))), T (let ((x1 5)) (macrolet ((segundo (x) `(cadr ,x))) (dm2b x1 (((segundo x2) x3 x4)) x5 x6))) \EV ((DM2B X1 (((SEGUNDO X2) X3 X4)) X5 X6) 5 (((SEGUNDO X2) X3 X4)) (CADR X2) (X3 X4) 5 (X5 X6)) \endcode \endissue{DEFMACRO-LAMBDA-LIST:TIGHTEN-DESCRIPTION} \label Affected By:\None. \label Exceptional Situations:\none. % adequately covered in the packages chapter. --sjl 5 Mar 92 % \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} % The consequences are undefined if \param{name} % is a \term{symbol} in \thepackage{common-lisp}. % \endissue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} % Barmar writes: % "Macros must not modify any of the structure they are given." % We outlawed displacing at some point. % but I couldn't find anything to back up this claim. Issue MACRO-CACHING % had this in mind, but didn't go far enough. So I've left this alone for now. % -kmp 2-Aug-91 \label See Also:: \issue{DEFINE-COMPILER-MACRO:X3J13-NOV89} \macref{define-compiler-macro}, \endissue{DEFINE-COMPILER-MACRO:X3J13-NOV89} \macref{destructuring-bind}, \funref{documentation}, \funref{macroexpand}, \varref{*macroexpand-hook*}, \specref{macrolet}, \funref{macro-function}, {\secref\Evaluation}, {\secref\Compilation}, {\secref\DocVsDecls} \label Notes:\None. \endissue{DECLS-AND-DOC} \endcom %%% ========== MACRO-FUNCTION \begincom{macro-function}\ftype{Accessor} \label Syntax:: \DefunWithValues macro-function {symbol {\opt} environment} {function} \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} % % If it's an error to supply the environment argument here, the syntax % % shouldn't show it. Compare w/COMPILER-MACRO-FUNCTION. --sjl 5 Mar 92 % % \Defsetf macro-function {symbol {\opt} environment} {new-function} % \Defsetf macro-function {symbol} {new-function} %% Reinstated per X3J13. \Defsetf macro-function {symbol {\opt} environment} {new-function} \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \label Arguments and Values:: \param{symbol}---a \term{symbol}. \issue{MACRO-FUNCTION-ENVIRONMENT} \param{environment}---an \term{environment} \term{object}. \endissue{MACRO-FUNCTION-ENVIRONMENT} \param{function}---a \term{macro function} or \nil. \param{new-function}---a \term{macro function}. \label Description:: %% 8.1.0 2 Determines whether \param{symbol} has a function definition as a macro in the specified \param{environment}. If so, the macro expansion function, a function of two arguments, is returned. If \param{symbol} has no function definition in the lexical environment \param{environment}, or its definition is not a \term{macro}, \funref{macro-function} returns \nil. \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \issue{MACRO-FUNCTION-ENVIRONMENT} % The consequences are undefined if \param{environment} is supplied % in a use of \funref{macro-function} as a \macref{setf} location specifier. \endissue{MACRO-FUNCTION-ENVIRONMENT} \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} %This doesn't belong here. -kmp 09-Apr-91 % \issue{MACRO-ENVIRONMENT-EXTENT:DYNAMIC} % The \term{environment} \term{object} has % \term{dynamic extent}; the consequences are undefined if % the \keyref{environment} argument is % referred to outside the \term{dynamic extent} % of the macro expansion function. % \endissue{MACRO-ENVIRONMENT-EXTENT:DYNAMIC} \issue{MACRO-FUNCTION-ENVIRONMENT} % The following will be deleted: % % %% 8.1.0 4 % \funref{macro-function} % cannot be used to determine whether \param{symbol} names % a locally defined macro established by \specref{macrolet}; % %% or \specref{symbol-macrolet} % \funref{macro-function} can % examine only global definitions. \endissue{MACRO-FUNCTION-ENVIRONMENT} %% 8.1.0 3 It is possible for both \funref{macro-function} and \issue{SPECIAL-FORM-P-MISNOMER:RENAME} \funref{special-operator-p} \endissue{SPECIAL-FORM-P-MISNOMER:RENAME} to return \term{true} of \param{symbol}. The \term{macro} definition must be available for use by programs that understand only the standard \clisp\ \term{special forms}. \label Examples:: \code (defmacro macfun (x) '(macro-function 'macfun)) \EV MACFUN (not (macro-function 'macfun)) \EV \term{false} \endcode %;;--- The next four lines are not valid Common Lisp, as equal %;;--- is not defined for functions --Moon % (and (setf (macro-function 'macfun) #'equal) % (equal (macro-function 'macfun) #'equal)) \EV \term{true} % (macrolet ((macfun (x) "local")) % (equal (macro-function 'macfun) #'equal)) \EV \term{true} \issue{MACRO-FUNCTION-ENVIRONMENT} \code (macrolet ((foo (&environment env) (if (macro-function 'bar env) ''yes ''no))) (list (foo) (macrolet ((bar () :beep)) (foo)))) \EV (NO YES) \endcode \endissue{MACRO-FUNCTION-ENVIRONMENT} \label Affected By:: \f{(setf macro-function)}, \macref{defmacro}, and \specref{macrolet}. \label Exceptional Situations:: \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} The consequences are undefined if \param{environment} is \term{non-nil} in a use of \SETFof{macro-function}. \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \label See Also:: \macref{defmacro}, {\secref\Evaluation} \label Notes:: %% 8.1.0 5 \macref{setf} can be used with \funref{macro-function} to install a \term{macro} as a symbol's global function definition: \code (setf (macro-function symbol) fn) \endcode The value installed must be a \term{function} that accepts two arguments, the entire macro call and an \term{environment}, and computes the expansion for that call. Performing this operation causes \param{symbol} to have only that macro definition as its global function definition; any previous definition, whether as a \term{macro} or as a \term{function}, is lost. \endcom %%% ========== MACROEXPAND %%% ========== MACROEXPAND-1 \begincom{macroexpand, macroexpand-1}\ftype{Function} \label Syntax:: \DefunWithValues macroexpand {form {\opt} env} {expansion, expanded-p} \DefunWithValues macroexpand-1 {form {\opt} env} {expansion, expanded-p} \label Arguments and Values:: \param{form}---a \term{form}. \param{env}---an \term{environment} \term{object}. \Default{\nil} \param{expansion}---a \term{form}. \issue{MACROEXPAND-RETURN-VALUE:TRUE} \param{expanded-p}---a \term{generalized boolean}. \endissue{MACROEXPAND-RETURN-VALUE:TRUE} \label Description:: \funref{macroexpand} and \funref{macroexpand-1} expand \term{macros}. %% 8.2.0 2 %% 8.2.0 3 If \param{form} is a \term{macro form}, then \funref{macroexpand-1} expands the \term{macro form} call once. %% 8.2.0 7 \funref{macroexpand} repeatedly expands \param{form} until it is no longer a \term{macro form}. In effect, \funref{macroexpand} calls \funref{macroexpand-1} repeatedly until the \term{secondary value} it returns is \nil. %% 8.2.0 2 If \param{form} is a \term{macro form}, then the \param{expansion} is a \term{macro expansion} and \param{expanded-p} is \term{true}. Otherwise, the \param{expansion} is the given \param{form} and \param{expanded-p} is \term{false}. %% 8.2.0 4 Macro expansion is carried out as follows. Once \funref{macroexpand-1} has determined that the \param{form} is a \term{macro form}, it obtains an appropriate expansion \term{function} for the \term{macro} or \term{symbol macro}. The value of \varref{*macroexpand-hook*} is \issue{FUNCTION-TYPE:X3J13-MARCH-88} coerced to a \term{function} and \endissue{FUNCTION-TYPE:X3J13-MARCH-88} then called as a \term{function} of three arguments: the expansion \term{function}, the \param{form}, and the \param{env}. The \term{value} returned from this call is taken to be the expansion of the \param{form}. %% Augmented this first sentence to mention global environment %% and local symbol-macrolet definitions. -kmp 12-May-93 In addition to \term{macro} definitions in the global environment, any local macro definitions established within \param{env} by \specref{macrolet} or \specref{symbol-macrolet} are considered. If only \param{form} is supplied as an argument, then the environment is effectively null, and only global macro definitions as established by \macref{defmacro} are considered. %% Sandra addition \term{Macro} definitions are shadowed by local \term{function} definitions. %% end Sandra addition \label Examples:: \code (defmacro alpha (x y) `(beta ,x ,y)) \EV ALPHA (defmacro beta (x y) `(gamma ,x ,y)) \EV BETA (defmacro delta (x y) `(gamma ,x ,y)) \EV EPSILON (defmacro expand (form &environment env) (multiple-value-bind (expansion expanded-p) (macroexpand form env) `(values ',expansion ',expanded-p))) \EV EXPAND (defmacro expand-1 (form &environment env) (multiple-value-bind (expansion expanded-p) (macroexpand-1 form env) `(values ',expansion ',expanded-p))) \EV EXPAND-1 \medbreak ;; Simple examples involving just the global environment (macroexpand-1 '(alpha a b)) \EV (BETA A B), \term{true} (expand-1 (alpha a b)) \EV (BETA A B), \term{true} (macroexpand '(alpha a b)) \EV (GAMMA A B), \term{true} (expand (alpha a b)) \EV (GAMMA A B), \term{true} (macroexpand-1 'not-a-macro) \EV NOT-A-MACRO, \term{false} (expand-1 not-a-macro) \EV NOT-A-MACRO, \term{false} (macroexpand '(not-a-macro a b)) \EV (NOT-A-MACRO A B), \term{false} (expand (not-a-macro a b)) \EV (NOT-A-MACRO A B), \term{false} \medbreak ;; Examples involving lexical environments (macrolet ((alpha (x y) `(delta ,x ,y))) (macroexpand-1 '(alpha a b))) \EV (BETA A B), \term{true} (macrolet ((alpha (x y) `(delta ,x ,y))) (expand-1 (alpha a b))) \EV (DELTA A B), \term{true} (macrolet ((alpha (x y) `(delta ,x ,y))) (macroexpand '(alpha a b))) \EV (GAMMA A B), \term{true} (macrolet ((alpha (x y) `(delta ,x ,y))) (expand (alpha a b))) \EV (GAMMA A B), \term{true} (macrolet ((beta (x y) `(epsilon ,x ,y))) (expand (alpha a b))) \EV (EPSILON A B), \term{true} (let ((x (list 1 2 3))) (symbol-macrolet ((a (first x))) (expand a))) \EV (FIRST X), \term{true} (let ((x (list 1 2 3))) (symbol-macrolet ((a (first x))) (macroexpand 'a))) \EV A, \term{false} (symbol-macrolet ((b (alpha x y))) (expand-1 b)) \EV (ALPHA X Y), \term{true} (symbol-macrolet ((b (alpha x y))) (expand b)) \EV (GAMMA X Y), \term{true} (symbol-macrolet ((b (alpha x y)) (a b)) (expand-1 a)) \EV B, \term{true} (symbol-macrolet ((b (alpha x y)) (a b)) (expand a)) \EV (GAMMA X Y), \term{true} \medbreak ;; Examples of shadowing behavior (flet ((beta (x y) (+ x y))) (expand (alpha a b))) \EV (BETA A B), \term{true} (macrolet ((alpha (x y) `(delta ,x ,y))) (flet ((alpha (x y) (+ x y))) (expand (alpha a b)))) \EV (ALPHA A B), \term{false} (let ((x (list 1 2 3))) (symbol-macrolet ((a (first x))) (let ((a x)) (expand a)))) \EV A, \term{false} \endcode \label Affected By:: \macref{defmacro}, \macref{setf} of \macref{macro-function}, \specref{macrolet}, \specref{symbol-macrolet} \label Exceptional Situations:\None. \label See Also:: \varref{*macroexpand-hook*}, \macref{defmacro}, \macref{setf} of \macref{macro-function}, \specref{macrolet}, \specref{symbol-macrolet}, {\secref\Evaluation} \label Notes:: Neither \funref{macroexpand} nor \funref{macroexpand-1} makes any explicit attempt to expand \term{macro forms} that are either \term{subforms} of the \param{form} or \term{subforms} of the \param{expansion}. Such expansion might occur implicitly, however, due to the semantics or implementation of the \term{macro function}. \endcom \issue{ISO-COMPATIBILITY:ADD-SUBSTRATE} %%% ========== DEFINE-SYMBOL-MACRO \begincom{define-symbol-macro}\ftype{Macro} \label Syntax:: \DefmacWithValuesNewline define-symbol-macro {symbol expansion} {symbol} \label Arguments and Values:: \param{symbol}---a \term{symbol}. \param{expansion}---a \term{form}. \label Description:: Provides a mechanism for globally affecting the \term{macro expansion} of the indicated \param{symbol}. Globally establishes an expansion function for the \term{symbol macro} named by \param{symbol}. %% Patterned after wording from SYMBOL-MACROLET (per issue SYMBOL-MACROLET-SEMANTICS). The only guaranteed property of an expansion \term{function} for a \term{symbol macro} is that when it is applied to the \term{form} and the \term{environment} it returns the correct expansion. (In particular, it is \term{implementation-dependent} whether the expansion is conceptually stored in the expansion function, the \term{environment}, or both.) Each global reference to \param{symbol} (\ie not \term{shadowed}\meaning{2} by a \term{binding} for a \term{variable} or \term{symbol macro} named by the same \term{symbol}) is expanded by the normal macro expansion process; \seesection\SymbolsAsForms. The expansion of a \term{symbol macro} is subject to further \term{macro expansion} in the same \term{lexical environment} as the \term{symbol macro} reference, exactly analogous to normal \term{macros}. %% Patterned after wording from SYMBOL-MACROLET (per issue SYMBOL-MACROLET-DECLARE). The consequences are unspecified if a \declref{special} declaration is made for \param{symbol} while in the scope of this definition (\ie when it is not \term{shadowed}\meaning{2} by a \term{binding} for a \term{variable} or \term{symbol macro} named by the same \term{symbol}). Any use of \specref{setq} to set the value of %% Per X3J13. -kmp 5-Oct-93 %one of the \param{symbol} while in the scope of this definition is treated as if it were a \macref{setf}. \macref{psetq} of \param{symbol} is treated as if it were a \macref{psetf}, and \macref{multiple-value-setq} is treated as if it were a \specref{setf} of \funref{values}. A \term{binding} for a \term{symbol macro} can be \term{shadowed}\meaning{2} by \specref{let} or \specref{symbol-macrolet}. \label Examples:: \code (defvar *things* (list 'alpha 'beta 'gamma)) \EV *THINGS* (define-symbol-macro thing1 (first *things*)) \EV THING1 (define-symbol-macro thing2 (second *things*)) \EV THING2 (define-symbol-macro thing3 (third *things*)) \EV THING3 thing1 \EV ALPHA (setq thing1 'ONE) \EV ONE *things* \EV (ONE BETA GAMMA) (multiple-value-setq (thing2 thing3) (values 'two 'three)) \EV TWO thing3 \EV THREE *things* \EV (ONE TWO THREE) (list thing2 (let ((thing2 2)) thing2)) \EV (TWO 2) \endcode \label Affected By:\None. \label Exceptional Situations:: %% See issues LISP-SYMBOL-REDEFINITION and SYMBOL-MACROS-AND-PROCLAIMED-SPECIALS. If \param{symbol} is already defined as a \term{global variable}, an error \oftype{program-error} is signaled. \label See Also:: \specref{symbol-macrolet}, \funref{macroexpand} \label Notes:\None. \endcom%{define-symbol-macro} \endissue{ISO-COMPATIBILITY:ADD-SUBSTRATE} %%% ========== SYMBOL-MACROLET \begincom{symbol-macrolet}\ftype{Special Operator} \issue{DECLS-AND-DOC} \issue{SYMBOL-MACROLET-SEMANTICS:SPECIAL-FORM} \label Syntax:: \DefspecWithValuesNewline symbol-macrolet {\paren{\starparen{symbol expansion}} \starparam{declaration} \starparam{form}} {\starparam{result}} \label Arguments and Values:: \param{symbol}---a \term{symbol}. \param{expansion}---a \term{form}. \issue{SYMBOL-MACROLET-DECLARE:ALLOW} \param{declaration}---a \misc{declare} \term{expression}; \noeval. \endissue{SYMBOL-MACROLET-DECLARE:ALLOW} \param{forms}---an \term{implicit progn}. \param{results}---the \term{values} returned by the \param{forms}. \label Description:: %A number of changes in here due to Moore #1 (first public review). \specref{symbol-macrolet} provides a mechanism for affecting the \term{macro expansion} environment for \term{symbols}. \specref{symbol-macrolet} lexically establishes expansion functions for each of the \term{symbol macros} named by \param{symbols}. \issue{SYMBOL-MACROLET-SEMANTICS:SPECIAL-FORM} The only guaranteed property of an expansion \term{function} for a \term{symbol macro} is that when it is applied to the \term{form} and the \term{environment} it returns the correct expansion. (In particular, it is \term{implementation-dependent} whether the expansion is conceptually stored in the expansion function, the \term{environment}, or both.) \endissue{SYMBOL-MACROLET-SEMANTICS:SPECIAL-FORM} Each reference to \param{symbol} as a variable within the lexical \term{scope} of \specref{symbol-macrolet} is expanded by the normal macro expansion process; \seesection\SymbolsAsForms. The expansion of a symbol macro is subject to further macro expansion in the same lexical environment as the symbol macro invocation, exactly analogous to normal \term{macros}. \issue{SYMBOL-MACROLET-DECLARE:ALLOW} Exactly the same \param{declarations} are allowed as for \specref{let} with one exception: \specref{symbol-macrolet} signals an error if a \declref{special} declaration names one of the \term{symbols} being defined by \specref{symbol-macrolet}. % Discussion of declarations moved to TYPE dictionary entry. --sjl 5 Mar 92 \endissue{SYMBOL-MACROLET-DECLARE:ALLOW} When the \param{forms} of the \specref{symbol-macrolet} form are expanded, any use of \specref{setq} to set the value of one of the specified variables is treated as if it were a \macref{setf}. \macref{psetq} of a \term{symbol} defined as a symbol macro is treated as if it were a \macref{psetf}, and \macref{multiple-value-setq} is treated as if it were a \specref{setf} of \funref{values}. The use of \specref{symbol-macrolet} can be shadowed by \specref{let}. In other words, \specref{symbol-macrolet} only substitutes for occurrences of \param{symbol} that would be in the \term{scope} of a lexical binding of \param{symbol} surrounding the \param{forms}. \label Examples:: \code ;;; The following is equivalent to ;;; (list 'foo (let ((x 'bar)) x)), ;;; not ;;; (list 'foo (let (('foo 'bar)) 'foo)) (symbol-macrolet ((x 'foo)) (list x (let ((x 'bar)) x))) \EV (foo bar) \NV (foo foo) (symbol-macrolet ((x '(foo x))) (list x)) \EV ((FOO X)) \endcode \label Affected By:\None. \label Exceptional Situations:: \issue{SYMBOL-MACROS-AND-PROCLAIMED-SPECIALS:SIGNALS-AN-ERROR} \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} If an attempt is made to bind a \term{symbol} that is defined as a \term{global variable}, an error \oftype{program-error} is signaled. \endissue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} \endissue{SYMBOL-MACROS-AND-PROCLAIMED-SPECIALS:SIGNALS-AN-ERROR} If \param{declaration} contains a \declref{special} declaration that names one of the \term{symbols} being bound by \specref{symbol-macrolet}, an error \oftype{program-error} is signaled. \label See Also:: \macref{with-slots}, \funref{macroexpand} \label Notes:: The special form \specref{symbol-macrolet} is the basic mechanism that is used to implement \macref{with-slots}. If a \specref{symbol-macrolet} \term{form} is a \term{top level form}, the \param{forms} are also processed as \term{top level forms}. \Seesection\FileCompilation. \endissue{SYMBOL-MACROLET-SEMANTICS:SPECIAL-FORM} \endissue{DECLS-AND-DOC} \endcom %%% ========== *MACROEXPAND-HOOK* \begincom{*macroexpand-hook*}\ftype{Variable} \issue{FUNCTION-TYPE:X3J13-MARCH-88} \label Value Type:: a \term{designator} for a \term{function} of three \term{arguments}: a \term{macro function}, a \term{macro form}, and an \term{environment} \term{object}. \label Initial Value:: \issue{MACROEXPAND-HOOK-DEFAULT:EXPLICITLY-VAGUE} \issue{MACROEXPAND-HOOK-INITIAL-VALUE:IMPLEMENTATION-DEPENDENT} a \term{designator} for a function that is equivalent to \thefunction{funcall}, but that might have additional \term{implementation-dependent} side-effects. \endissue{MACROEXPAND-HOOK-INITIAL-VALUE:IMPLEMENTATION-DEPENDENT} \endissue{MACROEXPAND-HOOK-DEFAULT:EXPLICITLY-VAGUE} \label Description:: %% 8.2.0 7 Used as the expansion interface hook by \funref{macroexpand-1} to control the \term{macro expansion} process. When a \term{macro form} is to be expanded, this \term{function} is called with three arguments: the \term{macro function}, the \term{macro form}, and the \term{environment} in which the \term{macro form} is to be expanded. \issue{MACRO-ENVIRONMENT-EXTENT:DYNAMIC} The \term{environment} \term{object} has \term{dynamic extent}; the consequences are undefined if the \term{environment} \term{object} is referred to outside the \term{dynamic extent} of the macro expansion function. \endissue{MACRO-ENVIRONMENT-EXTENT:DYNAMIC} \label Examples:: \code (defun hook (expander form env) (format t "Now expanding: ~S~%" form) (funcall expander form env)) \EV HOOK (defmacro machook (x y) `(/ (+ ,x ,y) 2)) \EV MACHOOK (macroexpand '(machook 1 2)) \EV (/ (+ 1 2) 2), \term{true} (let ((*macroexpand-hook* #'hook)) (macroexpand '(machook 1 2))) \OUT Now expanding (MACHOOK 1 2) \EV (/ (+ 1 2) 2), \term{true} \endcode \label Affected By:\None. \label See Also:: \funref{macroexpand}, \funref{macroexpand-1}, \funref{funcall}, {\secref\Evaluation} \label Notes:: The net effect of the chosen initial value is to just invoke the \term{macro function}, giving it the \term{macro form} and \term{environment} as its two arguments. Users or user programs can \term{assign} this \term{variable} to customize or trace the \term{macro expansion} mechanism. Note, however, that this \term{variable} is a global resource, potentially shared by multiple \term{programs}; as such, if any two \term{programs} depend for their correctness on the setting of this \term{variable}, those \term{programs} may not be able to run in the same \term{Lisp image}. For this reason, it is frequently best to confine its uses to debugging situations. \issue{MACROEXPAND-HOOK-INITIAL-VALUE:IMPLEMENTATION-DEPENDENT} Users who put their own function into \varref{*macroexpand-hook*} should consider saving the previous value of the hook, and calling that value from their own. \endissue{MACROEXPAND-HOOK-INITIAL-VALUE:IMPLEMENTATION-DEPENDENT} \endissue{FUNCTION-TYPE:X3J13-MARCH-88} \endcom %-------------------- Declarations -------------------- %%% ========== PROCLAIM \begincom{proclaim}\ftype{Function} \label Syntax:: \DefunWithValues proclaim {declaration-specifier} {\term{implementation-dependent}} \label Arguments and Values:: \param{declaration-specifier}---a \term{declaration specifier}. \label Description:: %% 9.1.0 11 \term{Establishes} the \term{declaration} specified by \param{declaration-specifier} in the \term{global environment}. %% 9.1.0 13 Such a \term{declaration}, sometimes called a \term{global declaration} or a \term{proclamation}, is always in force unless locally \term{shadowed}. %% 9.1.0 12 \term{Names} of \term{variables} and \term{functions} within \param{declaration-specifier} refer to \term{dynamic variables} and global \term{function} definitions, respectively. \Thenextfigure\ shows a list of \param{declaration identifiers} that can be used with \funref{proclaim}. % IGNORE, IGNORABLE, and DYNAMIC-EXTENT removed as consequence of vote % taken at 5-Oct-93 X3J13 meeting. \issue{DYNAMIC-EXTENT:NEW-DECLARATION} \issue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} \displayfour{Global Declaration Specifiers}{ declaration&inline&optimize&type\cr ftype¬inline&special&\cr } %function removed. \endissue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} \endissue{DYNAMIC-EXTENT:NEW-DECLARATION} %% 9.2.0 20 An implementation is free to support other (\term{implementation-defined}) \term{declaration identifiers} as well. \label Examples:: \code (defun declare-variable-types-globally (type vars) (proclaim `(type ,type ,@vars)) type) ;; Once this form is executed, the dynamic variable *TOLERANCE* ;; must always contain a float. (declare-variable-types-globally 'float '(*tolerance*)) \EV FLOAT \endcode \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \specref{declaim}, \misc{declare}, {\secref\Compilation} \label Notes:: Although the \term{execution} of a \funref{proclaim} \term{form} has effects that might affect compilation, the compiler does not make any attempt to recognize and specially process \funref{proclaim} \term{forms}. A \term{proclamation} such as the following, even if a \term{top level form}, does not have any effect until it is executed: \code (proclaim '(special *x*)) \endcode If compile time side effects are desired, \specref{eval-when} may be useful. For example: \code (eval-when (:execute :compile-toplevel :load-toplevel) (proclaim '(special *x*))) \endcode In most such cases, however, it is preferrable to use \macref{declaim} for this purpose. \issue{DECLARE-MACROS:FLUSH} Since \funref{proclaim} \term{forms} are ordinary \term{function forms}, \term{macro forms} can expand into them. %Barrett: So what? %Sandra: DUMB! %KMP: Tough. I think this is a commonly asked question, and perfectly % appropriate for a Note even though it's not a revelation. Technically, % anything in the Notes should be describable as "so what?" or "dumb" % or we should ask why it's in the Notes and not the Description. \endissue{DECLARE-MACROS:FLUSH} \endcom %%% ========== DECLAIM \begincom{declaim}\ftype{Macro} \issue{PROCLAIM-ETC-IN-COMPILE-FILE:NEW-MACRO} \label Syntax:: \DefmacWithValues declaim {\starparam{declaration-specifier}} {\term{implementation-dependent}} \label Arguments and Values:: \param{declaration-specifier}---a \term{declaration specifier}; \noeval. \label Description:: Establishes the \term{declarations} specified by the \param{declaration-specifiers}. If a use of this macro appears as a \term{top level form} in a \term{file} being processed by the \term{file compiler}, the proclamations are also made at compile-time. As with other defining macros, it is unspecified whether or not the compile-time side-effects of a \macref{declaim} persist after the \term{file} has been \term{compiled}. \label Examples:: \label Side Effects:\None. \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \misc{declare}, \funref{proclaim} \label Notes:\None. %!!! How does proclaim relate to declaim. % Not quite as simple as % (declaim ) == (eval-when (:compile-toplevel :load-toplevel :execute) (proclaim ')) % but close... % Clarify that calls to PROCLAIM should be treated the same as any % other function call. Users should wrap an explicit EVAL-WHEN around % top-level calls to PROCLAIM if they want them to affect compilation, % or use the macro DECLAIM. \endissue{PROCLAIM-ETC-IN-COMPILE-FILE:NEW-MACRO} \endcom %%% ========== DECLARE \begincom{declare}\ftype{Symbol} %!!! Barmar: This entry needs A LOT of work. It is highly redundant and perhaps inconsistent. \label Syntax:: \Defspec declare {\starparam{declaration-specifier}} \label Arguments:: %% 9.1.0 6 \param{declaration-specifier}---a \term{declaration specifier}; \noeval. \label Description:: %% 9.1.0 2 A \misc{declare} \term{expression}, sometimes called a \term{declaration}, can occur only at the beginning of the bodies of certain \term{forms}; that is, it may be preceded only by other \misc{declare} \term{expressions}, or by a \term{documentation string} if the context permits. A \misc{declare} \term{expression} can occur in a \term{lambda expression} or in any of the \term{forms} listed in \thenextfigure. \issue{DECLS-AND-DOC} \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \issue{SYMBOL-MACROLET-DECLARE:ALLOW} \issue{WITH-ADDED-METHODS:DELETE} \issue{GENERIC-FLET-POORLY-DESIGNED:DELETE} \displaythree{Standardized Forms In Which Declarations Can Occur}{ defgeneric&do-external-symbols&prog\cr define-compiler-macro&do-symbols&prog*\cr define-method-combination&dolist&restart-case\cr define-setf-expander&dotimes&symbol-macrolet\cr defmacro&flet&with-accessors\cr defmethod&handler-case&with-hash-table-iterator\cr defsetf&labels&with-input-from-string\cr deftype&let&with-open-file\cr defun&let*&with-open-stream\cr destructuring-bind&locally&with-output-to-string\cr do¯olet&with-package-iterator\cr do*&multiple-value-bind&with-slots\cr do-all-symbols&pprint-logical-block&\cr } %Deleted GENERIC-FLET, GENERIC-LABELS, GENERIC-FUNCTION -kmp 7-Feb-92 %Deleted WITH-ADDED-METHODS. -kmp 7-Jan-91 %Added DEFINE-COMPILER-MACRO, DESTRUCTURING-BIND, HANDLER-CASE, % PPRINT-LOGICAL-BLOCK, RESTART-CASE, WITH-HASH-TABLE-ITERATOR, % and WITH-PACKAGE-ITERATOR. -kmp 15-Feb-92 \endissue{GENERIC-FLET-POORLY-DESIGNED:DELETE} \endissue{WITH-ADDED-METHODS:DELETE} \endissue{SYMBOL-MACROLET-DECLARE:ALLOW} \endissue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \endissue{DECLS-AND-DOC} A \misc{declare} \term{expression} can only occur where specified by the syntax of these \term{forms}. %% 9.1.0 3 The consequences of attempting to evaluate a \misc{declare} \term{expression} are undefined. In situations where such \term{expressions} can appear, explicit checks are made for their presence and they are never actually evaluated; it is for this reason that they are called ``\misc{declare} \term{expressions}'' rather than ``\misc{declare} \term{forms}.'' % This doesn't belong here. I think it is adequately covered by the % discussion of lambda lists and scoping of lambda variables. --sjl 5 mar 92 % When evaluating a \term{lambda form}, % none of the \term{bound declarations} made by \misc{declare} \term{expressions} % appearing at the beginning of the body % of the \term{lambda expression} apply to the \term{argument} \term{evaluations}. % However, such \term{declarations} apply to the \term{initialization form} code (if any) % for \keyref{optional}, \keyref{key}, and \keyref{aux} \term{bindings} % % Added to please KMP (and hopefully Moon, too). % subsequent to the \term{name} to which the \term{bound declaration} refers; % \seesection\DeclScope. \issue{DECLARE-MACROS:FLUSH} %\term{macro} %calls may expand into declarations as long as this syntax is observed. \term{Macro forms} cannot expand into declarations; \misc{declare} \term{expressions} must appear as actual \term{subexpressions} of the \term{form} to which they refer. % the only valid declarations are \term{lists} whose \term{car} is the symbol \misc{declare}. %% Removed because this is already said in PROCLAIM. % \term{Macro forms} can expand into \funref{proclaim} forms, however. \endissue{DECLARE-MACROS:FLUSH} \Thenextfigure\ shows a list of \term{declaration identifiers} that can be used with \misc{declare}. \issue{DYNAMIC-EXTENT:NEW-DECLARATION} \issue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} \displaythree{Local Declaration Specifiers}{ dynamic-extent&ignore&optimize\cr ftype&inline&special\cr ignorable¬inline&type\cr } %function removed. \endissue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} \endissue{DYNAMIC-EXTENT:NEW-DECLARATION} %% 9.2.0 20 An implementation is free to support other (\term{implementation-defined}) \term{declaration identifiers} as well. \label Examples:: \code (defun nonsense (k x z) (foo z x) ;First call to foo (let ((j (foo k x)) ;Second call to foo (x (* k k))) (declare (inline foo) (special x z)) (foo x j z))) ;Third call to foo \endcode In this example, the \declref{inline} declaration applies only to the third call to \f{foo}, but not to the first or second ones. The \declref{special} declaration of \f{x} causes \specref{let} to make a dynamic \term{binding} for \f{x}, and causes the reference to \f{x} in the body of \specref{let} to be a dynamic reference. The reference to \f{x} in the second call to \f{foo} is a local reference to the second parameter of {\tt nonsense}. The reference to \f{x} in the first call to \f{foo} is a local reference, not a \declref{special} one. The \declref{special} declaration of \f{z} causes the reference to \f{z} in the %Added for Moon: third call to \f{foo} to be a dynamic reference; it does not refer to the parameter to \f{nonsense} named \f{z}, because that parameter \term{binding} has not been declared to be \declref{special}. (The \declref{special} declaration of \f{z} does not appear in the body of \macref{defun}, but in an inner \term{form}, and therefore does not affect the \term{binding} of the \term{parameter}.) \label Affected By:\None. \label Exceptional Situations:: The consequences of trying to use a \misc{declare} \term{expression} as a \term{form} to be \term{evaluated} are undefined. \editornote{KMP: Probably we need to say something here about ill-formed declare expressions.} \label See Also:: \funref{proclaim}, \secref\TypeSpecifiers, \declref{declaration}, \declref{dynamic-extent}, \declref{ftype}, \declref{ignorable}, \declref{ignore}, \declref{inline}, \declref{notinline}, \declref{optimize}, \declref{type} \label Notes:\None. %In all cases such additional code is within the scope of any \term{pervasive} %declarations appearing before the body of the \term{form}. %Declarations that affect \term{bindings} %have no effect on such code, except (of course) %in those situations where the code is defined to be within the scope %of the variables affected by such non-\term{pervasive} declarations. %%% 9.1.0 3 %Those \term{forms} that permit declarations to appear %perform explicit checks for their presence. \endcom %%% ========== IGNORE %%% ========== IGNORABLE \begincom{ignore, ignorable}\ftype{Declaration} \issue{DOTIMES-IGNORE:X3J13-MAR91} \label Syntax:: \f{\paren{ignore \star{\curly{\param{var} | \paren{\misc{function} \param{fn}}}}}} \f{\paren{ignorable \star{\curly{\param{var} | \paren{\misc{function} \param{fn}}}}}} \label Arguments:: \param{var}---a \term{variable} \term{name}. \param{fn}---a \term{function} \term{name}. \label Valid Context:: \term{declaration} %% Removed per X3J13 -kmp 4-Oct-93 %or \term{proclamation} \label Binding Types Affected:: \term{variable}, \term{function} \label Description:: \issue{IGNORE-USE-TERMINOLOGY:VALUE-ONLY} The \declref{ignore} and \declref{ignorable} declarations refer to \term{for-value} \term{references} to \term{variable} \term{bindings} for the \param{vars} and to \term{function} \term{bindings} for the \param{fns}. An \declref{ignore} \term{declaration} specifies that \term{for-value} \term{references} to the indicated \term{bindings} will not occur within the scope of the \term{declaration}. Within the \term{scope} of such a \term{declaration}, it is desirable for a compiler to issue a warning about the presence of either a \term{for-value} \term{reference} to any \param{var} or \param{fn}, or a \declref{special} \term{declaration} for any \param{var}. An \declref{ignorable} \term{declaration} specifies that \term{for-value} \term{references} to the indicated \term{bindings} might or might not occur within the scope of the \term{declaration}. Within the \term{scope} of such a \term{declaration}, it is not desirable for a compiler to issue a warning about the presence or absence of either a \term{for-value} \term{reference} to any \param{var} or \param{fn}, or a \declref{special} \term{declaration} for any \param{var}. When not within the \term{scope} of a \declref{ignore} or \declref{ignorable} \term{declaration}, it is desirable for a compiler to issue a warning about any \param{var} for which there is neither a \term{for-value} \term{reference} nor a \declref{special} \term{declaration}, or about any \param{fn} for which there is no \term{for-value} \term{reference}. Any warning about a ``used'' or ``unused'' \term{binding} must be \oftype{style-warning}, and may not affect program semantics. \endissue{IGNORE-USE-TERMINOLOGY:VALUE-ONLY} %!!! Maybe separate out to a concept section? %!!! Once these functions are described as using stream vars, % we can maybe remove this enumeration. % Alternatively, we could make a table and put it in the chapter of "general rules". The \term{stream variables} established by \macref{with-open-file}, \macref{with-open-stream}, \macref{with-input-from-string}, and \macref{with-output-to-string}, and all \term{iteration variables} are, by definition, always ``used''. Using \f{(declare (ignore \param{v}))}, for such a \term{variable} \param{v} has unspecified consequences. \endissue{DOTIMES-IGNORE:X3J13-MAR91} \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} % % added. I interpolated the bit about ignorable, since this was % % not covered in the original proposal. --sjl 4 Mar 92 % \issue{MACRO-DECLARATIONS:MAKE-EXPLICIT} % \declref{ignore} and \declref{ignorable} declarations may apply to % \term{symbol macros}. Such a declaration specifies that the named % \term{symbol macro} must not (in the case of \declref{ignore}) or % may not (in the case of \declref{ignorable}) be referenced within % the scope of the declaration. % \endissue{MACRO-DECLARATIONS:MAKE-EXPLICIT} \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \label See Also:: \misc{declare} %% Removed per X3J13. -kmp 4-Oct-93 % , \macref{declaim}, % \funref{proclaim} \endcom %%% ========== DYNAMIC-EXTENT \begincom{dynamic-extent}\ftype{Declaration} \label Syntax:: \f{(dynamic-extent \interleave{\starparam{var} | \star{\paren{\misc{function} \param{fn}}}})} \label Arguments:: \param{var}---a \term{variable} \term{name}. \param{fn}---a \term{function} \term{name}. \label Valid Context:: \term{declaration} %% Removed per X3J13 -kmp 4-Oct-93 %or \term{proclamation} \label Binding Types Affected:: \term{variable}, \term{function} \label Description:: \issue{DYNAMIC-EXTENT:NEW-DECLARATION} %!!! This needs work. -kmp 23-Aug-91 % Suppose that form contains a DYNAMIC-EXTENT declaration for % variable (which need not be bound by ). Consider the values % , ..., taken on by during the course of some execution of % . The declaration asserts that if object is an OIP of % when ever becomes the value of , then just after execution of % terminates will be either inaccessible or still an OIP of . In some containing \term{form}, \param{F}, this declaration asserts for each \param{var$\sub{i}$} (which need not be bound by \param{F}), and for each \term{value} \param{v$\sub{ij}$} that \param{var$\sub{i}$} takes on, and for each \term{object} \param{x$\sub{ijk}$} that %% Removed per Moon %\param{v$\sub{ij}$} is an \term{otherwise inaccessible part} of \param{v$\sub{ij}$} at any time when %% "it" => V[ij] per Moon %it \param{v$\sub{ij}$} becomes the value of \param{var$\sub{i}$}, that just after the execution of \param{F} terminates, \param{x$\sub{ijk}$} is either \term{inaccessible} (if \param{F} established a \term{binding} for \param{var$\sub{i}$}) or still an \term{otherwise inaccessible part} of the current value of \param{var$\sub{i}$} (if \param{F} did not establish a \term{binding} for \param{var$\sub{i}$}). \issue{DYNAMIC-EXTENT-FUNCTION:EXTEND} % The \param{var} may either be a symbol naming a variable, % or a list of the form {\tt (function \i{name})} which names a function. The same relation holds for each \param{fn$\sub{i}$}, except that the \term{bindings} are in the \term{function} \term{namespace}. \endissue{DYNAMIC-EXTENT-FUNCTION:EXTEND} The compiler is permitted to use %make whatever optimizations are appropriate given %% For RPG: this information in any way that is appropriate to the \term{implementation} and that does not conflict with the semantics of \clisp. \declref{dynamic-extent} declarations can be \term{free declarations} or \term{bound declarations}. % added. --sjl 4 Mar 92 \issue{MACRO-DECLARATIONS:MAKE-EXPLICIT} The \param{vars} and \param{fns} named in a \declref{dynamic-extent} declaration must not refer to \term{symbol macro} or \term{macro} bindings. \endissue{MACRO-DECLARATIONS:MAKE-EXPLICIT} \label Examples:: Since stack allocation of the initial value entails knowing at the \term{object}'s creation time that the \term{object} can be \term{stack-allocated}, it is not generally useful to make a \declref{dynamic-extent} \term{declaration} for \term{variables} which have no lexically apparent initial value. For example, it is probably useful to write: \code (defun f () (let ((x (list 1 2 3))) (declare (dynamic-extent x)) ...)) \endcode This would permit those compilers that wish to do so to \term{stack allocate} the list held by the local variable {\tt x}. It is permissible, but in practice probably not as useful, to write: \code (defun g (x) (declare (dynamic-extent x)) ...) (defun f () (g (list 1 2 3))) \endcode Most compilers would probably not \term{stack allocate} the \term{argument} to {\tt g} in {\tt f} because it would be a modularity violation for the compiler to assume facts about {\tt g} from within {\tt f}. Only an implementation that was willing to be responsible for recompiling {\tt f} if the definition of {\tt g} changed incompatibly could legitimately \term{stack allocate} the \term{list} argument to {\tt g} in {\tt f}. Here is another example: \code (declaim (inline g)) (defun g (x) (declare (dynamic-extent x)) ...) (defun f () (g (list 1 2 3))) (defun f () (flet ((g (x) (declare (dynamic-extent x)) ...)) (g (list 1 2 3)))) \endcode In the previous example, some compilers might determine that optimization was possible and others might not. A variant of this is the so-called ``stack allocated rest list'' that can be achieved (in implementations supporting the optimization) by: \code (defun f (&rest x) (declare (dynamic-extent x)) ...) \endcode Note that although the initial value of {\tt x} is not explicit, the {\tt f} function is responsible for assembling the list {\tt x} from the passed arguments, so the {\tt f} function can be optimized by the compiler to construct a \term{stack-allocated} list instead of a heap-allocated list in implementations that support such. In the following example, \code (let ((x (list 'a1 'b1 'c1)) (y (cons 'a2 (cons 'b2 (cons 'c2 nil))))) (declare (dynamic-extent x y)) ...) \endcode The \term{otherwise inaccessible parts} of {\tt x} are three \term{conses}, and the \term{otherwise inaccessible parts} of {\tt y} are three other \term{conses}. None of the symbols {\tt a1}, {\tt b1}, {\tt c1}, {\tt a2}, {\tt b2}, {\tt c2}, or \nil\ is an \term{otherwise inaccessible part} of {\tt x} or {\tt y} because each is \term{interned} and hence \term{accessible} by the \term{package} (or \term{packages}) in which it is \term{interned}. However, if a freshly allocated \term{uninterned} \term{symbol} had been used, it would have been an \term{otherwise inaccessible part} of the \term{list} which contained it. \code ;; In this example, the implementation is permitted to \term{stack allocate} ;; the list that is bound to X. (let ((x (list 1 2 3))) (declare (dynamic-extent x)) (print x) :done) \OUT (1 2 3) \EV :DONE ;; In this example, the list to be bound to L can be \term{stack-allocated}. (defun zap (x y z) (do ((l (list x y z) (cdr l))) ((null l)) (declare (dynamic-extent l)) (prin1 (car l)))) \EV ZAP (zap 1 2 3) \OUT 123 \EV NIL ;; Some implementations might open-code LIST-ALL-PACKAGES in a way ;; that permits using \term{stack allocation} of the list to be bound to L. (do ((l (list-all-packages) (cdr l))) ((null l)) (declare (dynamic-extent l)) (let ((name (package-name (car l)))) (when (string-search "COMMON-LISP" name) (print name)))) \OUT "COMMON-LISP" \OUT "COMMON-LISP-USER" \EV NIL ;; Some implementations might have the ability to \term{stack allocate} ;; rest lists. A declaration such as the following should be a cue ;; to such implementations that stack-allocation of the rest list ;; would be desirable. (defun add (&rest x) (declare (dynamic-extent x)) (apply #'+ x)) \EV ADD (add 1 2 3) \EV 6 (defun zap (n m) ;; Computes (RANDOM (+ M 1)) at relative speed of roughly O(N). ;; It may be slow, but with a good compiler at least it ;; doesn't waste much heap storage. :-\} (let ((a (make-array n))) (declare (dynamic-extent a)) (dotimes (i n) (declare (dynamic-extent i)) (setf (aref a i) (random (+ i 1)))) (aref a m))) \EV ZAP (< (zap 5 3) 3) \EV \term{true} \endcode The following are in error, since the value of {\tt x} is used outside of its \term{extent}: \code (length (list (let ((x (list 1 2 3))) ; Invalid (declare (dynamic-extent x)) x))) (progn (let ((x (list 1 2 3))) ; Invalid (declare (dynamic-extent x)) x) nil) \endcode \endissue{DYNAMIC-EXTENT:NEW-DECLARATION} \label See Also:: \misc{declare} %% Removed per X3J13. -kmp 4-Oct-93 % , \macref{declaim}, % \funref{proclaim} \label Notes:: The most common optimization is to \term{stack allocate} the initial value of the \term{objects} named by the \param{vars}. It is permissible for an implementation to simply ignore this declaration. \endcom %%% ========== TYPE \begincom{type}\ftype{Declaration} \label Syntax:: \f{(type \param{typespec} \starparam{var})} \f{(\param{typespec} \starparam{var})} \label Arguments:: \param{typespec}---a \term{type specifier}. \param{var}---a \term{variable} \term{name}. \label Valid Context:: \term{declaration} or \term{proclamation} \label Binding Types Affected:: \term{variable} \label Description:: Affects only variable \term{bindings} and specifies that the \param{vars} take on values only of the specified \param{typespec}. In particular, values assigned to the variables by \specref{setq}, as well as the initial values of the \param{vars} must be of the specified \param{typespec}. \declref{type} declarations never apply to function \term{bindings} (see \declref{ftype}). %% This is already said in the stuff on COMMON-LISP package. %% !!! Maybe add a cross-reference? -kmp 9-Feb-92 % \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} % Except where explicitly allowed, the consequences are undefined if a % \term{symbol} in \thepackage{common-lisp} is used as a % \param{var} argument. % If such a \term{symbol} is not globally % defined % %"by this standard" added per barmar: -kmp 28-Dec-90 % by this standard % as a variable or a constant, it is allowed to lexically bind it % and to declare the {\tt type} of that \term{binding}. For example, % the lexical variable names {\tt list} and {\tt car} are permitted. % \editornote{KMP: This is unintelligible to me and needs to be rewritten to clarify % that binding CL special variables is ok, but that their type decls are lexical.} % \endissue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} \issue{SYMBOL-MACROLET-DECLARE:ALLOW} A type declaration of a \term{symbol} defined by \specref{symbol-macrolet} is equivalent to wrapping a \specref{the} expression around the expansion of that \term{symbol}, \endissue{SYMBOL-MACROLET-DECLARE:ALLOW} % moved here from symbol-macrolet dictionary entry --sjl 5 mar 92 \issue{SYMBOL-MACROLET-TYPE-DECLARATION:NO} although the \term{symbol}'s \term{macro expansion} is not actually affected. \endissue{SYMBOL-MACROLET-TYPE-DECLARATION:NO} \issue{DECLARE-TYPE-FREE:LEXICAL} The meaning of a type declaration is equivalent to changing each reference to a variable (\param{var}) within the scope of the declaration to {\tt (the \param{typespec} \param{var})}, changing each expression assigned to the variable (\param{new-value}) within the scope of the declaration to {\tt (the \param{typespec} \param{new-value})}, and executing {\tt (the \param{typespec} \param{var})} at the moment the scope of the declaration is entered. A \term{type} declaration is valid in all declarations. The interpretation of a type declaration is as follows: \beginlist \itemitem{1.} During the execution of any reference to the declared variable within the scope of the declaration, the consequences are %"unspecified" -> "undefined" per barmar. i concur. -kmp %unspecified undefined if the value of the declared variable is not of the declared \term{type}. \itemitem{2.} During the execution of any \specref{setq} of the declared variable within the scope of the declaration, the consequences are %"unspecified" -> "undefined" per barmar. i concur. -kmp %unspecified undefined if the newly assigned value of the declared variable is not of the declared \term{type}. \itemitem{3.} At the moment the scope of the declaration is entered, the consequences are %"unspecified" -> "undefined" per barmar. i concur. -kmp %unspecified undefined if the value of the declared variable is not of the declared \term{type}. \endlist A \term{type} declaration affects only variable references within its scope. % and the meaning of free and "variable-binding-associated" type % declarations can be described identically. If nested \term{type} declarations refer to the same variable, then the value of the variable must be a member of the intersection of the declared \term{types}. \endissue{DECLARE-TYPE-FREE:LEXICAL} \issue{SPECIAL-TYPE-SHADOWING:CLARIFY} If there is a local {\tt type} declaration for a dynamic variable, and there is also a global {\tt type} proclamation for that same variable, then the value of the variable within the scope of the local declaration must be a member of the intersection of the two declared \term{types}. \endissue{SPECIAL-TYPE-SHADOWING:CLARIFY} \declref{type} declarations can be \term{free declarations} or \term{bound declarations}. \issue{TYPE-DECLARATION-ABBREVIATION:ALLOW-ALL} %!!! This paragraph might be better off elsewhere, but can live here for now. A \term{symbol} cannot be both the name of a \term{type} and the name of a declaration. Defining a \term{symbol} as the \term{name} of a \term{class}, \term{structure}, \term{condition}, or \term{type}, when the \term{symbol} has been \term{declared} as a declaration name, or vice versa, signals an error. \endissue{TYPE-DECLARATION-ABBREVIATION:ALLOW-ALL} %% The following was inserted after GLS checked this out. \issue{DECLARE-ARRAY-TYPE-ELEMENT-REFERENCES:RESTRICTIVE} Within the \term{lexical scope} of an \typeref{array} type declaration, all references to \term{array} \term{elements} are assumed to satisfy the \term{expressed array element type} (as opposed to the \term{upgraded array element type}). %The consequences are undefined if this is ever violated. A compiler can treat the code within the scope of the \typeref{array} type declaration as if each \term{access} of an \term{array} \term{element} were surrounded by an appropriate \specref{the} form. \endissue{DECLARE-ARRAY-TYPE-ELEMENT-REFERENCES:RESTRICTIVE} \label Examples:: \code (defun f (x y) (declare (type fixnum x y)) (let ((z (+ x y))) (declare (type fixnum z)) z)) \EV F (f 1 2) \EV 3 ;; The previous definition of F is equivalent to (defun f (x y) ;; This declaration is a shorthand form of the TYPE declaration (declare (fixnum x y)) ;; To declare the type of a return value, it's not necessary to ;; create a named variable. A THE special form can be used instead. (the fixnum (+ x y))) \EV F (f 1 2) \EV 3 \endcode \issue{DECLARE-ARRAY-TYPE-ELEMENT-REFERENCES:RESTRICTIVE} % There were some comments on this code (from the Cleanup issue, probably) % that no one liked, so I removed them. This example might do better with % some explanation, but better no explanation than a broken one. -kmp 14-Feb-92 \code (defvar *one-array* (make-array 10 :element-type '(signed-byte 5))) (defvar *another-array* (make-array 10 :element-type '(signed-byte 8))) (defun frob (an-array) (declare (type (array (signed-byte 5) 1) an-array)) (setf (aref an-array 1) 31) (setf (aref an-array 2) 127) (setf (aref an-array 3) (* 2 (aref an-array 3))) (let ((foo 0)) (declare (type (signed-byte 5) foo)) (setf foo (aref an-array 0)))) (frob *one-array*) (frob *another-array*) \endcode \medbreak The above definition of \f{frob} is equivalent to: \code (defun frob (an-array) (setf (the (signed-byte 5) (aref an-array 1)) 31) (setf (the (signed-byte 5) (aref an-array 2)) 127) (setf (the (signed-byte 5) (aref an-array 3)) (* 2 (the (signed-byte 5) (aref an-array 3)))) (let ((foo 0)) (declare (type (signed-byte 5) foo)) (setf foo (the (signed-byte 5) (aref an-array 0))))) \endcode %!!! Barmar: What does upgrading matter? Given an implementation in which \term{fixnums} are 29 bits but \typeref{fixnum} \term{arrays} are upgraded to signed 32-bit \term{arrays}, the following %% "should->could" per barmar. i concur. -kmp 27-Dec-90 %should could be compiled with all \term{fixnum} arithmetic: \code (defun bump-counters (counters) (declare (type (array fixnum *) bump-counters)) (dotimes (i (length counters)) (incf (aref counters i)))) \endcode \endissue{DECLARE-ARRAY-TYPE-ELEMENT-REFERENCES:RESTRICTIVE} \label See Also:: \misc{declare}, \macref{declaim}, \funref{proclaim} \label Notes:: \f{(\param{typespec} \starparam{var})} is an abbreviation for \f{(type \param{typespec} \starparam{var})}. \issue{TYPE-DECLARATION-ABBREVIATION:ALLOW-ALL} %provided that \param{typespec} is one of the standard \term{type specifier} %\term{symbols} in \figref\StandardizedAtomicTypeSpecs. \endissue{TYPE-DECLARATION-ABBREVIATION:ALLOW-ALL} A \declref{type} declaration for the arguments to a function does not necessarily imply anything about the type of the result. The following function is not permitted to be compiled using \term{implementation-dependent} \term{fixnum}-only arithmetic: \code (defun f (x y) (declare (fixnum x y)) (+ x y)) \endcode To see why, consider \f{(f most-positive-fixnum 1)}. Common Lisp defines that \f{F} must return a \term{bignum} here, rather than signal an error or produce a mathematically incorrect result. If you have special knowledge such ``\term{fixnum} overflow'' cases will not come up, you can declare the result value to be in the \term{fixnum} range, enabling some compilers to use more efficient arithmetic: \code (defun f (x y) (declare (fixnum x y)) (the fixnum (+ x y))) \endcode Note, however, that in the three-argument case, because of the possibility of an implicit intermediate value growing too large, the following will not cause \term{implementation-dependent} \term{fixnum}-only arithmetic to be used: \code (defun f (x y) (declare (fixnum x y z)) (the fixnum (+ x y z))) \endcode To see why, consider \f{(f most-positive-fixnum 1 -1).} Although the arguments and the result are all \term{fixnums}, an intermediate value is not a \term{fixnum}. If it is important that \term{implementation-dependent} \term{fixnum}-only arithmetic be selected in \term{implementations} that provide it, consider writing something like this instead: \code (defun f (x y) (declare (fixnum x y z)) (the fixnum (+ (the fixnum (+ x y)) z))) \endcode \endcom %%% ========== INLINE %%% ========== NOTINLINE \begincom{inline, notinline}\ftype{Declaration} \label Syntax:: {\tt (inline \starparam{function-name})} {\tt (notinline \starparam{function-name})} \label Arguments:: \param{function-name}---a \term{function name}. \label Valid Context:: \term{declaration} or \term{proclamation} \label Binding Types Affected:: \term{function} \label Description:: \issue{FUNCTION-NAME:LARGE} \declref{inline} specifies that it is desirable for the compiler to produce inline calls to the \term{functions} named by \param{function-names}; that is, the code for a specified \param{function-name} \endissue{FUNCTION-NAME:LARGE} should be integrated into the calling routine, appearing ``in line'' in place of a procedure call. %This declaration is \term{pervasive}. A compiler is free to ignore this declaration. \declref{inline} declarations never apply to variable \term{bindings}. %% 9.2.0 14 If one of the \term{functions} mentioned has a lexically apparent local definition (as made by \specref{flet} or \specref{labels}), then the declaration applies to that local definition and not to the global function definition. \issue{ALLOW-LOCAL-INLINE:INLINE-NOTINLINE} While no \term{conforming implementation} is required to perform inline expansion of user-defined functions, those \term{implementations} that do attempt to recognize the following paradigm: To define a \term{function} \f{f} that is not \declref{inline} by default but for which \f{(declare (inline f))} will make \param{f} be locally inlined, the proper definition sequence is: \code (declaim (inline f)) (defun f ...) (declaim (notinline f)) \endcode The \declref{inline} proclamation preceding the \macref{defun} \term{form} ensures that the \term{compiler} has the opportunity save the information necessary for inline expansion, and the \declref{notinline} proclamation following the \macref{defun} \term{form} prevents \f{f} from being expanded inline everywhere. \endissue{ALLOW-LOCAL-INLINE:INLINE-NOTINLINE} \issue{FUNCTION-NAME:LARGE} \declref{notinline} specifies that it is \endissue{FUNCTION-NAME:LARGE} undesirable to compile the \term{functions} named by \param{function-names} in-line. %This declaration is \term{pervasive}. A compiler is not free to ignore this declaration; %clarifying clause added per barmar. -kmp 28-Dec-90 calls to the specified functions must be implemented as out-of-line subroutine calls. %% 9.2.0 16 If one of the \term{functions} mentioned has a lexically apparent local definition (as made by \specref{flet} or \specref{labels}), then the declaration applies to that local definition and not to the global function definition. % added. --sjl 4 Mar 92 \issue{MACRO-DECLARATIONS:MAKE-EXPLICIT} In the presence of a \term{compiler macro} definition for \param{function-name}, a \declref{notinline} declaration prevents that \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \term{compiler macro} from being used. % in preference to the normal definition % of \param{function-name} as a \term{function} or \term{macro}. \endissue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} An \declref{inline} declaration may be used to encourage use of \term{compiler macro} definitions. \declref{inline} and \declref{notinline} declarations otherwise have no effect when the lexically visible definition of \param{function-name} is a \term{macro} definition. \endissue{MACRO-DECLARATIONS:MAKE-EXPLICIT} \declref{inline} and \declref{notinline} declarations can be \term{free declarations} or \term{bound declarations}. \declref{inline} and \declref{notinline} declarations of functions that appear before the body of a \specref{flet} or \specref{labels} \issue{WITH-ADDED-METHODS:DELETE} % \specref{with-added-methods}, \endissue{WITH-ADDED-METHODS:DELETE} \issue{GENERIC-FLET-POORLY-DESIGNED:DELETE} % \specref{generic-flet}, % and % \specref{generic-labels} \endissue{GENERIC-FLET-POORLY-DESIGNED:DELETE} \term{form} that defines that function are \term{bound declarations}. Such declarations in other contexts are \term{free declarations}. \label Examples:: \code ;; The globally defined function DISPATCH should be open-coded, ;; if the implementation supports inlining, unless a NOTINLINE ;; declaration overrides this effect. (declaim (inline dispatch)) (defun dispatch (x) (funcall (get (car x) 'dispatch) x)) ;; Here is an example where inlining would be encouraged. (defun top-level-1 () (dispatch (read-command))) ;; Here is an example where inlining would be prohibited. (defun top-level-2 () (declare (notinline dispatch)) (dispatch (read-command))) ;; Here is an example where inlining would be prohibited. (declaim (notinline dispatch)) (defun top-level-3 () (dispatch (read-command))) ;; Here is an example where inlining would be encouraged. (defun top-level-4 () (declare (inline dispatch)) (dispatch (read-command))) \endcode \label See Also:: \misc{declare}, \macref{declaim}, \funref{proclaim} \endcom %%% ========== FTYPE \begincom{ftype}\ftype{Declaration} \label Syntax:: \issue{FUNCTION-NAME:LARGE} \f{(ftype \param{type} \starparam{function-name})} \endissue{FUNCTION-NAME:LARGE} \label Arguments:: \param{function-name}---a \term{function name}. % added --sjl 7 Mar 92 \param{type}---a \term{type specifier}. \label Valid Context:: \term{declaration} or \term{proclamation} \label Binding Types Affected:: \term{function} \label Description:: Specifies that the \term{functions} named by \param{function-names} are of the functional type \param{type}. For example: \code (declare (ftype (function (integer list) t) ith) (ftype (function (number) float) sine cosine)) \endcode If one of the \term{functions} mentioned has a lexically apparent local definition (as made by \specref{flet} or \specref{labels}), then the declaration applies to that local definition and not to the global function definition. \declref{ftype} declarations never apply to variable \term{bindings} (see {\tt type}). % added. --sjl 4 Mar 92 \issue{MACRO-DECLARATIONS:MAKE-EXPLICIT} The lexically apparent bindings of \param{function-names} must not be \term{macro} definitions. (This is because \declref{ftype} declares the functional definition of each \term{function name} to be of a particular subtype of \typeref{function}, and \term{macros} do not denote \term{functions}.) \endissue{MACRO-DECLARATIONS:MAKE-EXPLICIT} % This is adequately covered in the packages chapter. --sjl 5 Mar 92 % \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} % Except where explicitly allowed, the consequences are undefined if % a \term{symbol} in \thepackage{common-lisp} % is used as a \param{function-name} argument. % If such a \term{symbol} is not defined % %"by this standard" added per barmar: -kmp 28-Dec-90 % by this standard % as a \term{function}, \term{macro}, or \term{special form}, % it is allowed to declare the % \declref{ftype} of that \term{binding}. % \endissue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} \declref{ftype} \issue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} %and \declref{function} \endissue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} declarations can be \term{free declarations} or \term{bound declarations}. \declref{ftype} declarations of functions that appear before the body of a \specref{flet} or \specref{labels} \issue{WITH-ADDED-METHODS:DELETE} % \specref{with-added-methods}, \endissue{WITH-ADDED-METHODS:DELETE} \issue{GENERIC-FLET-POORLY-DESIGNED:DELETE} % \specref{generic-flet}, % and % \specref{generic-labels} \endissue{GENERIC-FLET-POORLY-DESIGNED:DELETE} \term{form} that defines that function are \term{bound declarations}. Such declarations in other contexts are \term{free declarations}. \issue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} % % {\tt (function \param{var1} \param{var2}...)} % is equivalent to % {\tt (type function \param{var1} \param{var2}...)} % % %%% 9.2.0 12 %If one of the \term{functions} %mentioned has a lexically apparent local definition %(as made by \specref{flet} or \specref{labels}), then the declaration %applies to that local definition and not to the global function definition. % % % See \declref{type} and \declref{ftype}. % \endissue{DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION} \label See Also:: \misc{declare}, \macref{declaim}, \funref{proclaim} \endcom %%% ========== DECLARATION \begincom{declaration}\ftype{Declaration} \label Syntax:: \f{(declaration \starparam{name})} \label Arguments:: \param{name}---a \term{symbol}. \label Binding Types Affected:\None. \label Valid Context:: \term{proclamation} only \label Description:: %% 9.2.0 19 Advises the compiler that each \param{name} is a valid but potentially non-standard declaration name. The purpose of this is to tell one compiler not to issue warnings for declarations meant for another compiler or other program processor. % Already said in the packages chapter. --sjl 5 Mar 92 % \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} % The consequences are undefined if a \term{symbol} in \thepackage{common-lisp} % is used as a \i{name} argument. % \endissue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} %!!! Couldn't figure this out. It's obviously better to omit it than include it but... % \reviewer{Barmar: What does this mean??}%!!! % \f{(\i{declaration} x)} never applies to a \term{binding} of {\tt y}. \label Examples:: \code (declaim (declaration author target-language target-machine)) (declaim (target-language ada)) (declaim (target-machine IBM-650)) (defun strangep (x) (declare (author "Harry Tweeker")) (member x '(strange weird odd peculiar))) \endcode \label See Also:: \macref{declaim}, \funref{proclaim} \endcom %%% ========== OPTIMIZE %%% ========== COMPILATION-SPEED %%% ========== DEBUG %%% ========== SAFETY %%% ========== SPACE %%% ========== SPEED \begincom{optimize}\ftype{Declaration} \label Syntax:: \f{(optimize \star{\curly{\param{quality} | (\param{quality} \param{value})}})} \idxref{compilation-speed}% \idxref{debug}% \idxref{safety}% \idxref{space}% \idxref{speed} \label Arguments:: \param{quality}---an \term{optimize quality}. \param{value}---one of the \term{integers} \f{0}, \f{1}, \f{2}, or \f{3}. \label Valid Context:: \term{declaration} or \term{proclamation} \label Binding Types Affected:\None. \label Description:: Advises the compiler that each \param{quality} should be given attention according to the specified corresponding \param{value}. Each \param{quality} must be a \term{symbol} naming an \term{optimize quality}; the names and meanings of the standard \param{optimize qualities} are shown in \thenextfigure. \issue{OPTIMIZE-DEBUG-INFO:NEW-QUALITY} \tablefigtwo{Optimize qualities}{Name}{Meaning}{ \declref{compilation-speed} & speed of the compilation process \cr \declref{debug} & ease of debugging \cr \declref{safety} & run-time error checking \cr \declref{space} & both code size and run-time space \cr \declref{speed} & speed of the object code \cr } \endissue{OPTIMIZE-DEBUG-INFO:NEW-QUALITY} There may be other, \term{implementation-defined} \term{optimize qualities}. A \param{value} \f{0} means that the corresponding \param{quality} is totally unimportant, and \f{3} that the \param{quality} is extremely important; \f{1} and \f{2} are intermediate values, with \f{1} the %% "average" -> "neutral" since KAB balked and I think this will be less weird. -kmp 3-Oct-91 %average neutral value. \f{(\param{quality} 3)} can be abbreviated to \param{quality}. %This declaration is \term{pervasive}. Note that \term{code} which has the optimization \f{(safety 3)}, or just \typeref{safety}, is called \term{safe} \term{code}. % Added per Sandra in response to Barrett query ... The consequences are unspecified if a \param{quality} appears more than once with \term{different} \param{values}. \label Examples:: \code (defun often-used-subroutine (x y) (declare (optimize (safety 2))) (error-check x y) (hairy-setup x) (do ((i 0 (+ i 1)) (z x (cdr z))) ((null z)) ;; This inner loop really needs to burn. (declare (optimize speed)) (declare (fixnum i)) )) \endcode \label See Also:: \misc{declare}, \macref{declaim}, \funref{proclaim}, {\secref\DeclScope} \label Notes:: An \declref{optimize} declaration never applies to either a \term{variable} or a \term{function} \term{binding}. An \declref{optimize} declaration can only be a \term{free declaration}. For more information, \seesection\DeclScope. \endcom % I moved the dictionary entry for the special declaration here. % It used to be in chapter 5, but it seemed more logical to put it with % all the other declaration specifiers. -- sjl 5 Mar 92 %%% ========== SPECIAL \begincom{special}\ftype{Declaration} \label Syntax:: \f{(special \starparam{var})} \label Arguments:: \param{var}---a \term{symbol}. \label Valid Context:: \term{declaration} or \term{proclamation} \label Binding Types Affected:: \term{variable} \label Description:: Specifies that all of the \param{vars} named are dynamic. This specifier affects variable \term{bindings} and affects references. All variable \term{bindings} affected are made to be dynamic \term{bindings}, and affected variable references refer to the current dynamic \term{binding}. %rather than the current lexical \term{binding}. For example: \code (defun hack (thing *mod*) ;The binding of the parameter (declare (special *mod*)) ; *mod* is visible to hack1, (hack1 (car thing))) ; but not that of thing. (defun hack1 (arg) (declare (special *mod*)) ;Declare references to *mod* ;within hack1 to be special. (if (atom arg) *mod* (cons (hack1 (car arg)) (hack1 (cdr arg))))) \endcode %% 9.2.0 4 A \declref{special} declaration does not affect inner \term{bindings} of a \param{var}; the inner \term{bindings} implicitly shadow a \declref{special} declaration and must be explicitly re-declared to be \declref{special}. \declref{special} declarations never apply to function \term{bindings}. % adequately covered in the packages chapter. --sjl 5 Mar 92 % \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} % Except where explicitly allowed, the consequences are undefined if % a \term{symbol} in \thepackage{common-lisp} % is used as a \param{var} argument. % \endissue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} \declref{special} declarations can be either \term{bound declarations}, affecting both a binding and references, or \term{free declarations}, affecting only references, depending on whether the declaration is attached to a variable binding. %% 9.1.0 14 When used in a \term{proclamation}, a \declref{special} \term{declaration specifier} applies to all \term{bindings} as well as to all references of the mentioned variables. For example, after \code (declaim (special x)) \endcode then in a function definition such as \code (defun example (x) ...) \endcode the parameter \f{x} is bound as a dynamic variable rather than as a lexical variable. \label Examples:: \code (defun declare-eg (y) ;this y is special (declare (special y)) (let ((y t)) ;this y is lexical (list y (locally (declare (special y)) y)))) ;this y refers to the ;special binding of y \EV DECLARE-EG (declare-eg nil) \EV (T NIL) \endcode \code (setf (symbol-value 'x) 6) (defun foo (x) ;a lexical binding of x (print x) (let ((x (1+ x))) ;a special binding of x (declare (special x)) ;and a lexical reference (bar)) (1+ x)) (defun bar () (print (locally (declare (special x)) x))) (foo 10) \OUT 10 \OUT 11 \EV 11 \endcode \code (setf (symbol-value 'x) 6) (defun bar (x y) ;[1] 1st occurrence of x (let ((old-x x) ;[2] 2nd occurrence of x -- same as 1st occurrence (x y)) ;[3] 3rd occurrence of x (declare (special x)) (list old-x x))) (bar 'first 'second) \EV (FIRST SECOND) \endcode \code (defun few (x &optional (y *foo*)) (declare (special *foo*)) ...) \endcode The reference to \f{*foo*} in the first line of this example is not \declref{special} even though there is a \declref{special} declaration in the second line. \code (declaim (special prosp)) \EV \term{implementation-dependent} (setq prosp 1 reg 1) \EV 1 (let ((prosp 2) (reg 2)) ;the binding of prosp is special (set 'prosp 3) (set 'reg 3) ;due to the preceding proclamation, (list prosp reg)) ;whereas the variable reg is lexical \EV (3 2) (list prosp reg) \EV (1 3) (declaim (special x)) ;x is always special. (defun example (x y) (declare (special y)) (let ((y 3) (x (* x 2))) (print (+ y (locally (declare (special y)) y))) (let ((y 4)) (declare (special y)) (foo x)))) \EV EXAMPLE \endcode In the contorted code above, the outermost and innermost \term{bindings} of \f{y} are dynamic, but the middle binding is lexical. The two arguments to \f{+} are different, one being the value, which is \f{3}, of the lexical variable \f{y}, and the other being the value of the dynamic variable named \f{y} (a \term{binding} of which happens, coincidentally, to lexically surround it at an outer level). All the \term{bindings} of \f{x} and references to \f{x} are dynamic, however, because of the proclamation that \f{x} is always \declref{special}. \label See Also:: \macref{defparameter}, \macref{defvar} \endcom %%% ========== LOCALLY \begincom{locally}\ftype{Special Operator} \issue{DECLS-AND-DOC} \label Syntax:: \issue{LOCALLY-TOP-LEVEL:SPECIAL-FORM} \DefspecWithValues locally {\starparam{declaration} \starparam{form}} {\starparam{result}} \endissue{LOCALLY-TOP-LEVEL:SPECIAL-FORM} \label Arguments and Values:: \param{Declaration}---a \misc{declare} \term{expression}; \noeval. \param{forms}---an \term{implicit progn}. \issue{RETURN-VALUES-UNSPECIFIED:SPECIFY} \param{results}---the \term{values} of the \param{forms}. \endissue{RETURN-VALUES-UNSPECIFIED:SPECIFY} \label Description:: %% 9.1.0 10 Sequentially evaluates a body of \param{forms} in a \term{lexical environment} where the given \param{declarations} have effect. \label Examples:: \code (defun sample-function (y) ;this y is regarded as special (declare (special y)) (let ((y t)) ;this y is regarded as lexical (list y (locally (declare (special y)) ;; this next y is regarded as special y)))) \EV SAMPLE-FUNCTION (sample-function nil) \EV (T NIL) (setq x '(1 2 3) y '(4 . 5)) \EV (4 . 5) ;;; The following declarations are not notably useful in specific. ;;; They just offer a sample of valid declaration syntax using LOCALLY. (locally (declare (inline floor) (notinline car cdr)) (declare (optimize space)) (floor (car x) (cdr y))) \EV 0, 1 \endcode \issue{LOCALLY-TOP-LEVEL:SPECIAL-FORM} %Barmar: Say what the example does. %KMP: I added some comments. OK? \code ;;; This example shows a definition of a function that has a particular set ;;; of OPTIMIZE settings made locally to that definition. (locally (declare (optimize (safety 3) (space 3) (speed 0))) (defun frob (w x y &optional (z (foo x y))) (mumble x y z w))) \EV FROB ;;; This is like the previous example, except that the optimize settings ;;; remain in effect for subsequent definitions in the same compilation unit. (declaim (optimize (safety 3) (space 3) (speed 0))) (defun frob (w x y &optional (z (foo x y))) (mumble x y z w)) \EV FROB \endcode \endissue{LOCALLY-TOP-LEVEL:SPECIAL-FORM} \label Side Effects:\None. \label Affected By:\None. \label Exceptional Situations:\None. \label See Also:: \misc{declare} \label Notes:: The \declref{special} declaration may be used with \specref{locally} to affect references to, rather than \term{bindings} of, \term{variables}. %Barrett: So what? \issue{LOCALLY-TOP-LEVEL:SPECIAL-FORM} If a \specref{locally} \term{form} is a \term{top level form}, the body \param{forms} are also processed as \term{top level forms}. \Seesection\FileCompilation. \endissue{LOCALLY-TOP-LEVEL:SPECIAL-FORM} \endissue{DECLS-AND-DOC} \endcom %%% ========== THE \begincom{the}\ftype{Special Operator} \label Syntax:: \DefspecWithValues the {value-type form} {\starparam{result}} \label Arguments and Values:: \param{value-type}---a \term{type specifier}; \noeval. \param{form}---a \term{form}; \eval. \issue{THE-VALUES:RETURN-NUMBER-RECEIVED} %% 7.9.2 19 \param{results}---the \term{values} resulting from the \term{evaluation} of \param{form}. These \term{values} must conform to the \term{type} supplied by \param{value-type}; see below. \endissue{THE-VALUES:RETURN-NUMBER-RECEIVED} \label Description:: %% 9.3.0 2 \specref{the} specifies that the \term{values}\meaning{1a} returned by \param{form} are of the \term{types} specified by \param{value-type}. The consequences are undefined if any \param{result} is not of the declared type. \issue{THE-AMBIGUITY:FOR-DECLARATION} %% This text has been removed per Moon #19 (first public review). -kmp 8-May-93 % %!!! Barmar: If this is true, the THE form is equivalent to the form argument. % \param{Value-type} can be any valid \term{type specifier}. % In the case that \param{form} returns one % value and \param{value-type} is not a % \declref{values} \term{type specifier}, % % \code % (the type exp) % \EQ % (let ((#:g0001 exp)) % (declare (type type #:g0001)) % #:g0001) % \endcode \endissue{THE-AMBIGUITY:FOR-DECLARATION} \issue{JUN90-TRIVIAL-ISSUES:27} \issue{THE-VALUES:RETURN-NUMBER-RECEIVED} It is permissible for \param{form} to \term{yield} a different number of \term{values} than are specified by \param{value-type}, provided that the values for which \param{types} are declared are indeed of those \term{types}. Missing values are treated as \nil\ for the purposes of checking their \term{types}. Regardless of number of \term{values} declared by \param{value-type}, the number of \term{values} returned by \thespecform{the} is the same as the number of \term{values} returned by \param{form}. \endissue{THE-VALUES:RETURN-NUMBER-RECEIVED} \endissue{JUN90-TRIVIAL-ISSUES:27} \label Examples:: \issue{THE-VALUES:RETURN-NUMBER-RECEIVED} \code (the symbol (car (list (gensym)))) \EV #:G9876 (the fixnum (+ 5 7)) \EV 12 (the (values) (truncate 3.2 2)) \EV 1, 1.2 (the integer (truncate 3.2 2)) \EV 1, 1.2 (the (values integer) (truncate 3.2 2)) \EV 1, 1.2 (the (values integer float) (truncate 3.2 2)) \EV 1, 1.2 (the (values integer float symbol) (truncate 3.2 2)) \EV 1, 1.2 (the (values integer float symbol t null list) (truncate 3.2 2)) \EV 1, 1.2 (let ((i 100)) (declare (fixnum i)) (the fixnum (1+ i))) \EV 101 (let* ((x (list 'a 'b 'c)) (y 5)) (setf (the fixnum (car x)) y) x) \EV (5 B C) \endcode \endissue{THE-VALUES:RETURN-NUMBER-RECEIVED} \label Affected By:\None. \label Exceptional Situations:: The consequences are undefined if the \term{values} \term{yielded} by the \param{form} are not of the \term{type} specified by \param{value-type}. \label See Also:: \declref{values} \label Notes:: The \declref{values} \term{type specifier} can be used to indicate the types of \term{multiple values}: \code (the (values integer integer) (floor x y)) (the (values string t) (gethash the-key the-string-table)) \endcode \macref{setf} can be used with \specref{the} type declarations. In this case the declaration is transferred to the form that specifies the new value. The resulting \macref{setf} \term{form} is then analyzed. \endcom %-------------------- Introspection -------------------- %%% ========== SPECIAL-OPERATOR-P \begincom{special-operator-p}\ftype{Function} \issue{SPECIAL-FORM-P-MISNOMER:RENAME} \label Syntax:: \DefunWithValues special-operator-p {symbol} {generalized-boolean} \label Arguments and Values:: \param{symbol}---a \term{symbol}. \param{generalized-boolean}---a \term{generalized boolean}. \label Description:: %% 7.1.1 22 \Predicate{symbol}{a \term{special operator}} \label Examples:: \code (special-operator-p 'if) \EV \term{true} (special-operator-p 'car) \EV \term{false} (special-operator-p 'one) \EV \term{false} \endcode \label Side Effects:\None. \label Affected By:\None. \label Exceptional Situations:: Should signal \typeref{type-error} if its argument is not a \term{symbol}. \label See Also:\None. \label Notes:: Historically, this function was called \f{special-form-p}. The name was finally declared a misnomer and changed, since it returned true for \term{special operators}, not \term{special forms}. %This is beyond the scope of the language. -kmp 26-Dec-90 % A returned \term{non-nil} value is typically a \term{function} % of \term{implementation-dependent} nature that can be used to % interpret (evaluate) the \term{special form}. \endissue{SPECIAL-FORM-P-MISNOMER:RENAME} \endcom %%% ========== CONSTANTP \begincom{constantp}\ftype{Function} \issue{CONSTANTP-DEFINITION:INTENTIONAL} \issue{CONSTANTP-ENVIRONMENT:ADD-ARG} \label Syntax:: \DefunWithValues constantp {form {\opt} environment} {generalized-boolean} \label Arguments and Values:: \param{form}---a \term{form}. \param{environment}---an \term{environment} \term{object}. \Default{\nil} \param{generalized-boolean}---a \term{generalized boolean}. \label Description:: %% 20.1.0 14 %% 20.1.0 15 Returns \term{true} if \param{form} can be determined by the \term{implementation} to be a \term{constant form} in the indicated \param{environment}; otherwise, it returns \term{false} indicating either that the \term{form} is not a \term{constant form} or that it cannot be determined whether or not \term{form} is a \term{constant form}. The following kinds of \term{forms} are considered \term{constant forms}: \beginlist \itemitem{\bull} % This is the wrong term. --sjl 5 Mar 92 % \term{Constant objects} \term{Self-evaluating objects} (such as \term{numbers}, \term{characters}, and the various kinds of \term{arrays}) are always considered \term{constant forms} and must be recognized as such by \funref{constantp}. \itemitem{\bull} \term{Constant variables}, such as \term{keywords}, symbols defined by \clisp\ as constant (such as \nil, \t, and \conref{pi}), and symbols declared as constant by the user in the indicated \param{environment} using \macref{defconstant} are always considered \term{constant forms} and must be recognized as such by \funref{constantp}. \itemitem{\bull} \specref{quote} \term{forms} are always considered \term{constant forms} and must be recognized as such by \funref{constantp}. \itemitem{\bull} An \term{implementation} is permitted, but not required, to detect additional \term{constant forms}. If it does, it is also permitted, but not required, to make use of information in the \param{environment}. Examples of \term{constant forms} for which \funref{constantp} might or might not return \term{true} are: \f{(sqrt pi)}, \f{(+ 3 2)}, \f{(length '(a b c))}, and \f{(let ((x 7)) (zerop x))}. \endlist If an \term{implementation} chooses to make use of the \param{environment} information, such actions as expanding \term{macros} or performing function inlining are permitted to be used, but not required; however, expanding \term{compiler macros} is not permitted. \label Examples:: \code (constantp 1) \EV \term{true} (constantp 'temp) \EV \term{false} (constantp ''temp)) \EV \term{true} (defconstant this-is-a-constant 'never-changing) \EV THIS-IS-A-CONSTANT (constantp 'this-is-a-constant) \EV \term{true} (constantp "temp") \EV \term{true} (setq a 6) \EV 6 (constantp a) \EV \term{true} (constantp '(sin pi)) \EV \term{implementation-dependent} (constantp '(car '(x))) \EV \term{implementation-dependent} (constantp '(eql x x)) \EV \term{implementation-dependent} (constantp '(typep x 'nil)) \EV \term{implementation-dependent} (constantp '(typep x 't)) \EV \term{implementation-dependent} (constantp '(values this-is-a-constant)) \EV \term{implementation-dependent} (constantp '(values 'x 'y)) \EV \term{implementation-dependent} (constantp '(let ((a '(a b c))) (+ (length a) 6))) \EV \term{implementation-dependent} \endcode \label Side Effects:\None! \label Affected By:: The state of the global environment (\eg which \term{symbols} have been declared to be the \term{names} of \term{constant variables}). \label Exceptional Situations:\None! \label See Also:: \macref{defconstant} \label Notes:\None. \endissue{CONSTANTP-ENVIRONMENT:ADD-ARG} \endissue{CONSTANTP-DEFINITION:INTENTIONAL} \endcom \issue{SYNTACTIC-ENVIRONMENT-ACCESS:RETRACTED-MAR91} % The following functions were removed due to the retraction of % issue SYNTACTIC-ENVIRONMENT-ACCESS by X3J13 at the Mar 91 meeting. % AUGMENT-ENVIRONMENT % DECLARATION-INFORMATION % DEFINE-DECLARATION % ENCLOSE % FUNCTION-INFORMATION % PARSE-MACRO % VARIABLE-INFORMATION \endissue{SYNTACTIC-ENVIRONMENT-ACCESS:RETRACTED-MAR91}