1
0
Fork 0
cl-sites/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node104.html
2023-10-25 11:23:21 +02:00

465 lines
22 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
<HEAD>
<TITLE>9.1. Declaration Syntax</TITLE>
</HEAD>
<BODY>
<meta name="description" value=" Declaration Syntax">
<meta name="keywords" value="clm">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<b>Common Lisp the Language, 2nd Edition</b>
<BR> <HR><A NAME=tex2html2819 HREF="node105.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html2817 HREF="node103.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html2811 HREF="node103.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html2821 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html2822 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html2820 HREF="node105.html"> Declaration Specifiers</A>
<B>Up:</B> <A NAME=tex2html2818 HREF="node103.html"> Declarations</A>
<B> Previous:</B> <A NAME=tex2html2812 HREF="node103.html"> Declarations</A>
<HR> <P>
<H1><A NAME=SECTION001310000000000000000>9.1. Declaration Syntax</A></H1>
<P>
<A NAME=DECLARESYNTAXSECTION>The</A>
<tt>declare</tt> construct is used for embedding declarations within
executable code. Global declarations and declarations that are computed
by a program are established by the <tt>proclaim</tt> construct.
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in June 1989 (PROCLAIM-ETC-IN-COMPILE-FILE) <A NAME=9009>&#160;</A>
to introduce the new macro <tt>declaim</tt>, which is guaranteed
to be recognized appropriately by the compiler and is often more convenient
than <tt>proclaim</tt> for establishing global declarations.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
<BR><b>[Special Form]</b><BR>
<tt>declare</tt> <tt>{<i>decl-spec</i>}*</tt><P>A <tt>declare</tt> form is known as a <i>declaration</i>.
Declarations may occur only at the beginning of the bodies of
certain special forms;
that is, a declaration may occur only as a statement
of such a special form, and all statements preceding it (if any) must
also be <tt>declare</tt> forms (or possibly documentation strings, in some cases).
Declarations may occur in lambda-expressions and in the forms listed here.
<P><pre>
define-setf-method labels
defmacro let
defsetf let*
deftype locally
defun macrolet
do multiple-value-bind
do* prog
do-all-symbols prog*
do-external-symbols with-input-from-string
do-symbols with-open-file
dolist with-open-stream
dotimes with-output-to-string
flet
</pre><P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
<i>Notice of correction.</i>
In the first edition, the above list failed to mention the forms
<tt>define-setf-method</tt>, <tt>with-input-from-string</tt>, <tt>with-open-file</tt>,
<tt>with-open-stream</tt>, and <tt>with-output-to-string</tt>, even though
their individual descriptions in the first edition specified that declarations
may appear in those forms.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
X3J13 voted in June 1989 (CONDITION-RESTARTS) <A NAME=9053>&#160;</A> to add <tt>with-condition-restarts</tt>
and also (DATA-IO) <A NAME=9055>&#160;</A> to add <tt>print-unreadable-object</tt>
and <tt>with-standard-io-syntax</tt>.
The X3J13 vote left it unclear whether these macros
permit declarations to appear at the heads of their bodies.
I believe that was the intent,
but this is only my interpretation.
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in June 1988
(CLOS) <A NAME=9059>&#160;</A>
to adopt the Common Lisp Object System,
which includes the following additional forms in which declarations
may occur:
<P><pre>
defgeneric generic-function
define-method-combination generic-labels
defmethod with-added-methods
generic-flet
</pre><P>
Furthermore X3J13 voted in January 1989
(SYMBOL-MACROLET-DECLARE) <A NAME=9069>&#160;</A>
to allow declarations to
occur before the bodies of these forms:
<P><pre>
symbol-macrolet with-slots
with-accessors
</pre><P>
There are certain aspects peculiar to <tt>symbol-macrolet</tt>
(and therefore also to <tt>with-accessors</tt> and <tt>with-slots</tt>,
which expand into uses of <tt>symbol-macrolet</tt>).
An error is signaled if a name defined by <tt>symbol-macrolet</tt>
is declared <tt>special</tt>, and a type declaration of a name
defined by <tt>symbol-macrolet</tt> is equivalent in effect
to wrapping a <tt>the</tt> form mentioning that type around
the expansion of the defined symbol.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
It is an error to attempt to evaluate a declaration.
Those special forms that permit declarations to appear
perform explicit checks for their presence.
<P>
<hr>
<b>Compatibility note:</b> In MacLisp, <tt>declare</tt> is a special form
that does nothing but return the symbol <tt>declare</tt> as its
result. The MacLisp interpreter knows nothing about declarations
but just blindly evaluates them, effectively ignoring them.
The MacLisp compiler recognizes declarations but processes
them simply by evaluating the subforms of the declaration in
the compilation context. In Common Lisp it is
important that both the interpreter and compiler recognize
declarations (especially <tt>special</tt> declarations) and treat them
consistently,
and so the rules about the structure and use of declarations
have been made considerably more stringent.
The odd tricks played in MacLisp by writing arbitrary forms
to be evaluated within a <tt>declare</tt> form
are better done in both MacLisp and Common Lisp by using <tt>eval-when</tt>.
<hr>
<P>
It is permissible for a macro call to expand into a declaration
and be recognized as such, provided that the macro call
appears where a declaration may legitimately appear.
(However, a macro call may not appear in place of a <i>decl-spec</i>.)
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in March 1988
(DECLARE-MACROS) <A NAME=9093>&#160;</A>
to eliminate the recognition of
a declaration resulting from the expansion of a macro call.
This feature proved to be seldom used and
awkward to implement in interpreters, compilers, and other code-analyzing programs.
<P>
Under this change, a declaration is recognized only as such if
it appears explicitly, as a list whose <i>car</i> is the symbol <tt>declare</tt>,
in the body of a relevant special form. (Note, however, that it
is still possible for a macro to expand into a call to the <tt>proclaim</tt>
function.)
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
Each <i>decl-spec</i> is a list whose <i>car</i> is a symbol
specifying the kind of declaration to be made. Declarations may be
divided into two classes: those that concern the bindings of variables,
and those that do not. (The <tt>special</tt> declaration is the sole
exception: it effectively falls into both classes, as explained below.)
Those that concern variable bindings apply
only to the bindings made by the form at the head of whose body they
appear. For example, in
<P><pre>
(defun foo (x)
(declare (type float x)) ...
(let ((x 'a)) ...)
...)
</pre><P>
the <tt>type</tt> declaration applies only to the outer binding of <tt>x</tt>,
and not to the binding made in the <tt>let</tt>.
<P>
<hr>
<b>Compatibility note:</b> This represents a difference from MacLisp, in which type
declarations are pervasive.
<hr>
<P>
Declarations that do not concern themselves with variable bindings are
pervasive, affecting all code in the body of the special form.
As an example of a pervasive declaration,
<P><pre>
(defun foo (x y) (declare (notinline floor)) ...)
</pre><P>
advises that everywhere within the body of <tt>foo</tt> the function
<tt>floor</tt> should not be open-coded but called as an out-of-line subroutine.
<P>
Some special forms contain pieces of code that, properly speaking,
are not part of the body of the special form. Examples of this
are initialization forms that provide values for bound variables,
and the result forms of iteration constructs.
In all cases such additional code is within the scope of any pervasive
declarations appearing before the body of the special form.
Non-pervasive declarations 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-pervasive declarations.
For example:
<P><pre>
(defun few (x <tt>&amp;optional</tt> (y *print-circle*))
(declare (special *print-circle*))
...)
</pre><P>
The reference to <tt>*print-circle*</tt> in the first line of this example is special
because of the declaration in the second line.
<P><pre>
(defun nonsense (k x z)
(foo z x) ;First call to <tt>foo</tt>
(let ((j (foo k x)) ;Second call to <tt>foo</tt>
(x (* k k)))
(declare (inline foo) (special x z))
(foo x j z))) ;Third call to <tt>foo</tt>
</pre><P>
In this rather nonsensical example,
the <tt>inline</tt> declaration applies to the
second and third calls to <tt>foo</tt>, but not to the first one.
The <tt>special</tt> declaration of <tt>x</tt> causes the <tt>let</tt> form
to make a special binding for <tt>x</tt> and causes the reference to <tt>x</tt>
in the body of the <tt>let</tt> to be a special reference.
The reference to <tt>x</tt> in the second call to <tt>foo</tt> is also a special
reference.
The reference to <tt>x</tt> in the first call to <tt>foo</tt> is a local
reference, not a special one. The <tt>special</tt> declaration of <tt>z</tt>
causes the reference to <tt>z</tt> in the call
to <tt>foo</tt> to be a special reference; it will not
refer to the parameter to <tt>nonsense</tt> named <tt>z</tt>, because that
parameter binding has not been declared to be <tt>special</tt>.
(The <tt>special</tt> declaration of <tt>z</tt> does not appear in the body
of the <tt>defun</tt>, but in an inner construct, and therefore does not
affect the binding of the parameter.)
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in January 1989
(DECLARATION-SCOPE) <A NAME=9144>&#160;</A>
to replace the rules concerning the scope of
declarations occurring at the head of a special form or lambda-expression:
<UL><LI> The scope of a declaration always includes the body forms, as well as any
``stepper'' or ``result'' forms (which are logically part of the body), of the
special form or lambda-expression.
<P>
<LI> If the declaration applies to a name binding, then the scope of the
declaration also includes the scope of the name binding.
</UL>
Note that
the distinction between pervasive and non-pervasive
declarations is eliminated. An important change
from the first edition is that ``initialization''
forms are specifically <i>not</i> included as part of the body under the first
rule; on the other hand, in many cases initialization forms may fall
within the scope of certain declarations under the second rule.
<P>
X3J13 also voted in January 1989
(DECLARE-TYPE-FREE) <A NAME=9150>&#160;</A>
to change the interpretation
of <tt>type</tt> declarations (see section <A HREF="node105.html#DECLARATIONSPECIFIERSSECTION">9.2</A>).
<P>
These changes affect the interpretation of some of the examples from the
first edition.
<P><pre>
(defun foo (x)
(declare (type float x)) ...
(let ((x 'a)) ...)
...)
</pre><P>
Under the interpretation approved by X3J13, the type
declaration applies to <i>both</i> bindings of <tt>x</tt>.
More accurately, the type declaration is considered to apply to
variable references rather than bindings, and the type declaration refers
to every reference in the body of <tt>foo</tt> to a variable named <tt>x</tt>,
no matter to what binding it may refer.
<P><pre>
(defun foo (x y) (declare (notinline floor)) ...)
</pre><P>
This example of the use of <tt>notinline</tt> stands unchanged, but the following
slight extension of it would change:
<P><pre>
(defun foo (x &amp;optional (y (floor x)))
(declare (notinline floor)) ...)
</pre><P>
Under first edition rules, the <tt>notinline</tt> declaration would be
considered to apply to the call to <tt>floor</tt> in the initialization
form for <tt>y</tt>. Under the interpretation approved by X3J13, the
<tt>notinline</tt> would <i>not</i> apply to that particular call to <tt>floor</tt>.
Instead the user must write something like
<P><pre>
(defun foo (x &amp;optional (y (locally (declare (notinline floor))
(floor x))))
(declare (notinline floor)) ...)
</pre><P>
or perhaps
<P><pre>
(locally (declare (notinline floor))
(defun foo (x &amp;optional (y (floor x))) ...))
</pre><P>
Similarly, the <tt>special</tt> declaration in
<P><pre>
(defun few (x <tt>&amp;optional</tt> (y *print-circle*))
(declare (special *print-circle*))
...)
</pre><P>
is not considered to apply to the reference in the initialization form
for <tt>y</tt> in <tt>few</tt>. As for the <tt>nonsense</tt> example,
<P><pre>
(defun nonsense (k x z)
(foo z x) ;First call to <tt>foo</tt>
(let ((j (foo k x)) ;Second call to <tt>foo</tt>
(x (* k k)))
(declare (inline foo) (special x z))
(foo x j z))) ;Third call to <tt>foo</tt>
</pre><P>
under the interpretation approved by X3J13, the <tt>inline</tt>
declaration is no longer considered to apply to the second
call to <tt>foo</tt>, because it is in an initialization form, which is
no longer considered in the scope of the declaration. Similarly,
the reference to <tt>x</tt> in that second call to <tt>foo</tt> is no longer
taken to be a special reference, but a local reference to the second
parameter of <tt>nonsense</tt>.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
<BR><b>[Macro]</b><BR>
<tt>locally</tt> <tt>{<i>declaration</i>}*</tt> <tt>{<i>form</i>}*</tt><P>This macro may be used to make local pervasive declarations
where desired. It does not bind any variables and therefore cannot
be used meaningfully for declarations of variable bindings.
(Note that the <tt>special</tt> declaration may be used with <tt>locally</tt>
to pervasively affect references to, rather than bindings of, variables.)
For example:
<P><pre>
(locally (declare (inline floor) (notinline car cdr))
(declare (optimize space))
(floor (car x) (cdr y)))
</pre>
<img align=bottom alt="old_change_end" src="gif/old_change_end.gif">
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in January 1989
(RETURN-VALUES-UNSPECIFIED) <A NAME=9206>&#160;</A>
to specify that <tt>locally</tt> executes the <i>form</i>s as an implicit
<tt>progn</tt> and returns the value(s) of the last <i>form</i>.
<P>
X3J13 voted in March 1989 (LOCALLY-TOP-LEVEL) <A NAME=9213>&#160;</A> to make <tt>locally</tt>
be a special form rather than a macro. It still has the same syntax.
<P>
<BR><b>[Special Form]</b><BR>
<tt>locally</tt> <tt>{<i>declaration</i>}*</tt> <tt>{<i>form</i>}*</tt><P>This change was made to accommodate the new compilation model for top-level forms
in a file (see section <A HREF="node224.html#COMPILERSECTION">25.1</A>).
When a <tt>locally</tt> form appears at top level, the forms in its body are
processed as top-level forms. This means that one may, for example, meaningfully use
<tt>locally</tt> to wrap declarations around a <tt>defun</tt> or <tt>defmacro</tt> form:
<P><pre>
(locally
(declare (optimize (safety 3) (space 3) (debug 3) (speed 1)))
(defun foo (x &amp;optional (y (abs x)) (z (sqrt y)))
(bar x y z)))
</pre><P>
Without assurance that this works
one must write something cumbersome such as
<P><pre>
(defun foo (x &amp;optional (y (locally
(declare (optimize (safety 3)
(space 3)
(debug 3)
(speed 1)))
(abs x)))
(z (locally
(declare (optimize (safety 3)
(space 3)
(debug 3)
(speed 1)))
(sqrt y))))
(locally
(declare (optimize (safety 3) (space 3) (debug 3) (speed 1)))
(bar x y z)))
</pre>
<img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
<BR><b>[Function]</b><BR>
<tt>proclaim</tt> <tt><i>decl-spec</i></tt><P>The function <tt>proclaim</tt> takes a <i>decl-spec</i> as its
argument and puts it into effect globally. (Such a global
declaration is called a <i>proclamation</i>.)
Because <tt>proclaim</tt> is a function, its argument is always evaluated.
This allows a program to compute a declaration and then put
it into effect by calling <tt>proclaim</tt>.
<P>
Any variable names
mentioned are assumed to refer to the dynamic values of the
variable. For example, the proclamation
<P><pre>
(proclaim '(type float tolerance))
</pre><P>
once executed,
specifies that the dynamic value of <tt>tolerance</tt> should always
be a floating-point number.
Similarly, any function-names mentioned are assumed to refer to
the global function definition.
<P>
A proclamation constitutes a universal declaration, always in force
unless locally shadowed. For example,
<P><pre>
(proclaim '(inline floor))
</pre><P>
advises that <tt>floor</tt> should normally be open-coded in-line by the
compiler (but in the situation
<P><pre>
(defun foo (x y) (declare (notinline floor)) ...)
</pre><P>
it will be compiled out-of-line anyway in the body of <tt>foo</tt>,
because of the shadowing local declaration to that effect).
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in January 1989 (SPECIAL-TYPE-SHADOWING) <A NAME=9245>&#160;</A>
to clarify that such shadowing does not occur in the case of type declarations.
If there is a local type declaration for a special variable and there is also a global
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 types.
This is consistent with the treatment of nested local type declarations
on which X3J13 also voted in January 1989 (DECLARE-TYPE-FREE) <A NAME=9246>&#160;</A> .
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
As a special case (so to speak), <tt>proclaim</tt> treats a <tt>special</tt>
<i>decl-spec</i> as applying to all bindings as well as to
all references of the mentioned variables.
<p>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
<i>Notice of correction.</i>
In the first edition, this sentence referred to a ``<tt>special</tt>
<i>declaration-form</i>.'' That was incorrect; <tt>proclaim</tt> accepts
only a <i>decl-spec</i>, not a <i>declaration-form</i>.
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
For example, after
<P><pre>
(proclaim '(special x))
</pre><P>
in a function definition such as
<P><pre>
(defun example (x) ...)
</pre><P>
the parameter <tt>x</tt> will be bound as a special (dynamic) variable
rather than as a lexical (static) variable. This facility should
be used with caution. The usual way to define a globally special
variable is with <tt>defvar</tt> or <tt>defparameter</tt>.
<P>
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
X3J13 voted in June 1989 (PROCLAIM-ETC-IN-COMPILE-FILE) <A NAME=9268>&#160;</A>
to clarify that the compiler is not required to treat
calls to <tt>proclaim</tt> any differently from the way it treats
any other function call. If a top-level call to <tt>proclaim</tt>
is to take effect at compile time, it should be surrounded
by an appropriate <tt>eval-when</tt> form. Better yet,
the new macro <tt>declaim</tt> may be used instead.
<P>
<BR><b>[Macro]</b><BR>
<tt>declaim</tt> <tt>{<i>decl-spec</i>}*</tt><P>This macro is syntactically like <tt>declare</tt> and semantically
like <tt>proclaim</tt>. It is an executable form and may be used
anywhere <tt>proclaim</tt> may be called. However, each <i>decl-spec</i>
is not evaluated.
<P>
If a call to this macro appears at top level in a file
being processed by the 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
<tt>declaim</tt> persist after the file has been compiled
(see section <A HREF="node224.html#COMPILERSECTION">25.1</A>).
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
<P>
<BR> <HR><A NAME=tex2html2819 HREF="node105.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html2817 HREF="node103.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html2811 HREF="node103.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html2821 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html2822 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html2820 HREF="node105.html"> Declaration Specifiers</A>
<B>Up:</B> <A NAME=tex2html2818 HREF="node103.html"> Declarations</A>
<B> Previous:</B> <A NAME=tex2html2812 HREF="node103.html"> Declarations</A>
<HR> <P>
<HR>
<P><ADDRESS>
AI.Repository@cs.cmu.edu
</ADDRESS>
</BODY>