516 lines
24 KiB
HTML
516 lines
24 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>8.1. Macro Definition</TITLE>
|
|
</HEAD>
|
|
<BODY>
|
|
<meta name="description" value=" Macro Definition">
|
|
<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=tex2html2746 HREF="node99.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html2744 HREF="node97.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html2738 HREF="node97.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html2748 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html2749 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
|
<B> Next:</B> <A NAME=tex2html2747 HREF="node99.html"> Macro Expansion</A>
|
|
<B>Up:</B> <A NAME=tex2html2745 HREF="node97.html"> Macros</A>
|
|
<B> Previous:</B> <A NAME=tex2html2739 HREF="node97.html"> Macros</A>
|
|
<HR> <P>
|
|
<H1><A NAME=SECTION001210000000000000000>8.1. Macro Definition</A></H1>
|
|
<P>
|
|
The function <tt>macro-function</tt> determines whether a given symbol
|
|
is the name of a macro. The <tt>defmacro</tt> construct provides
|
|
a convenient way to define new macros.
|
|
<P>
|
|
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
|
|
<BR><b>[Function]</b><BR>
|
|
<tt>macro-function</tt> <tt><i>symbol</i></tt><P>The argument must be a symbol. If the symbol has a global function definition
|
|
that is a macro definition, then the expansion function
|
|
(a function of two arguments, the macro-call form and an environment)
|
|
is returned.
|
|
If the symbol has no global function definition, or has a definition
|
|
as an ordinary function or as a special form but not as a macro, then
|
|
<tt>nil</tt> is returned. The function <tt>macroexpand</tt>
|
|
is the best way to invoke the expansion function.
|
|
<P>
|
|
It is possible for <i>both</i> <tt>macro-function</tt> and <tt>special-form-p</tt>
|
|
to be true of a symbol. This is possible because an implementation is
|
|
permitted to implement any macro also as a special form for speed.
|
|
On the other hand, the macro definition must be available
|
|
for use by programs that understand only the standard special forms
|
|
listed in table <A HREF="node59.html#SPECIALFORMTABLE">5-1</A>.
|
|
<P>
|
|
<tt>macro-function</tt> cannot be used to determine whether a symbol names
|
|
a locally defined macro established by <tt>macrolet</tt>;
|
|
<tt>macro-function</tt> can
|
|
examine only global definitions.
|
|
<P>
|
|
<tt>setf</tt> may be used with <tt>macro-function</tt> to install
|
|
a macro as a symbol's global function definition:
|
|
<P><pre>
|
|
(setf (macro-function <i>symbol</i>) <i>fn</i>)
|
|
</pre><P>
|
|
The value installed must be a function that accepts two arguments,
|
|
an entire macro call and an environment, and computes the expansion for that call.
|
|
Performing this operation causes the symbol to have <i>only</i> that
|
|
macro definition as its global function definition; any previous
|
|
definition, whether as a macro or as a function, is lost.
|
|
It is an error to attempt to redefine the name of a special
|
|
form.
|
|
<br><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 March 1988 (MACRO-FUNCTION-ENVIRONMENT) <A NAME=8261> </A>
|
|
to add an optional environment argument to <tt>macro-function</tt>.
|
|
<P>
|
|
<BR><b>[Function]</b><BR>
|
|
<tt>macro-function</tt> <tt><i>symbol</i></tt> <tt>&optional</tt> <tt><i>env</i></tt><P>The first argument must be a symbol. If the symbol has a function definition
|
|
that is a macro definition, whether a local one established in the
|
|
environment <i>env</i> by <tt>macrolet</tt> or a global one established as
|
|
if by <tt>defmacro</tt>,
|
|
then the expansion function
|
|
(a function of two arguments, the macro-call form and an environment)
|
|
is returned.
|
|
If the symbol has no function definition, or has a definition
|
|
as an ordinary function or as a special form but not as a macro, then
|
|
<tt>nil</tt> is returned. The function <tt>macroexpand</tt> or <tt>macroexpand-1</tt>
|
|
is the best way to invoke the expansion function.
|
|
<P>
|
|
It is possible for <i>both</i> <tt>macro-function</tt> and <tt>special-form-p</tt>
|
|
to be true of a symbol. This is possible because an implementation is
|
|
permitted to implement any macro also as a special form for speed.
|
|
On the other hand, the macro definition must be available
|
|
for use by programs that understand only the standard special forms
|
|
listed in table <A HREF="node59.html#SPECIALFORMTABLE">5-1</A>.
|
|
<P>
|
|
<tt>setf</tt> may be used with <tt>macro-function</tt> to install
|
|
a macro as a symbol's global function definition:
|
|
<P><pre>
|
|
(setf (macro-function <i>symbol</i>) <i>fn</i>)
|
|
</pre><P>
|
|
The value installed must be a function that accepts two arguments,
|
|
an entire macro call and an environment, and computes the expansion for that call.
|
|
Performing this operation causes the symbol to have <i>only</i> that
|
|
macro definition as its global function definition; any previous
|
|
definition, whether as a macro or as a function, is lost.
|
|
One cannot use <tt>setf</tt> to establish a local macro definition;
|
|
it is an error to supply a second argument to <tt>macro-function</tt>
|
|
when using it with <tt>setf</tt>.
|
|
It is an error to attempt to redefine the name of a special form.
|
|
<P>
|
|
See also <tt>compiler-macro-function</tt>.
|
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
|
<P>
|
|
<BR><b>[Macro]</b><BR>
|
|
<pre>
|
|
defmacro <i>name</i> <i>lambda-list</i> <b>[[</b> {<i>declaration</i>}* | <i>doc-string</i> <b>]]</b> {<i>form</i>}*
|
|
</pre>
|
|
<P><tt>defmacro</tt> is a macro-defining macro that
|
|
arranges to decompose the macro-call form in an elegant and useful way.
|
|
<tt>defmacro</tt> has essentially the same syntax as <tt>defun</tt>: <i>name</i> is the
|
|
symbol whose macro definition we are creating, <i>lambda-list</i> is similar in
|
|
form to a lambda-list, and
|
|
the <i>form</i>s constitute the body of the expander function.
|
|
The <tt>defmacro</tt> construct arranges to install this expander function,
|
|
as the global macro definition of <i>name</i>.
|
|
<P>
|
|
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
|
|
The expander function
|
|
is effectively defined in the <i>global</i> environment;
|
|
lexically scoped entities established
|
|
outside the <tt>defmacro</tt> form that would ordinarily be lexically apparent
|
|
are not visible within the body of the expansion function.
|
|
<br><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 March 1989 (DEFINING-MACROS-NON-TOP-LEVEL) <A NAME=8303> </A>
|
|
to clarify that, while defining forms normally appear at top level,
|
|
it is meaningful to place them in non-top-level contexts.
|
|
Furthermore, <tt>defmacro</tt> should define the expander function
|
|
within the enclosing lexical environment, not within the global
|
|
environment.
|
|
<P>
|
|
X3J13 voted in March 1988 (FLET-IMPLICIT-BLOCK) <A NAME=8307> </A>
|
|
to specify that the body of the expander function defined
|
|
by <tt>defmacro</tt> is implicitly enclosed in a <tt>block</tt> construct
|
|
whose name is the same as the <i>name</i> of the defined macro.
|
|
Therefore <tt>return-from</tt> may be used to exit from the function.
|
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
|
<P>
|
|
The <i>name</i> is returned
|
|
as the value of the <tt>defmacro</tt> form.
|
|
<P>
|
|
If we view the
|
|
macro call as a list containing a function name and some argument forms,
|
|
in effect the expander function and the list of (unevaluated) argument
|
|
forms is given to <tt>apply</tt>.
|
|
The parameter specifiers are processed as for any lambda-expression,
|
|
using the macro-call argument forms as the arguments.
|
|
Then the body forms are evaluated
|
|
as an implicit <tt>progn</tt>, and the value of the last form
|
|
is returned as the expansion of the macro call.
|
|
<P>
|
|
If the optional documentation string <i>doc-string</i> is present (if not
|
|
followed by a declaration, it may be
|
|
present only if at least one <i>form</i> is also specified, as it is
|
|
otherwise taken to be a <i>form</i>), then it is attached to the <i>name</i>
|
|
as a documentation string of type <tt>function</tt>; see <tt>documentation</tt>.
|
|
<P>
|
|
<img align=bottom alt="old_change_begin" src="gif/old_change_begin.gif"><br>
|
|
Like the lambda-list in a <tt>defun</tt>, a <tt>defmacro</tt> <i>lambda-list</i> may contain
|
|
the lambda-list keywords <tt>&optional</tt>, <tt>&rest</tt>, <tt>&key</tt>,
|
|
<tt>&allow-other-keys</tt>, and <tt>&aux</tt>.
|
|
For <tt>&optional</tt> and <tt>&key</tt> parameters, initialization forms and
|
|
supplied-p parameters may be specified, just as for <tt>defun</tt>.
|
|
Three additional markers
|
|
are allowed in <tt>defmacro</tt> variable lists only.
|
|
<br><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>
|
|
These three markers are now allowed in other constructs as well.
|
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
|
<P>
|
|
<DL COMPACT>
|
|
<DT><tt>&body</tt>
|
|
<DD>
|
|
This is identical in function to <tt>&rest</tt>, but it informs certain
|
|
output-formatting and editing functions that the remainder of the form is
|
|
treated as a body and should be indented accordingly.
|
|
(Only one of <tt>&body</tt> or <tt>&rest</tt> may be used.)
|
|
<P>
|
|
<DT><tt>&whole</tt>
|
|
<DD>
|
|
This is followed by a single variable that is bound to the
|
|
entire macro-call form; this is the value that the macro definition function
|
|
receives as its single argument.
|
|
<tt>&whole</tt> and the following variable should appear first in the lambda-list,
|
|
before any other parameter or lambda-list keyword.
|
|
<P>
|
|
<DT><tt>&environment</tt>
|
|
<DD>
|
|
This is followed by a single variable that is bound
|
|
to an environment representing the lexical environment in which the
|
|
macro call is to be interpreted. This environment may not be the
|
|
complete lexical environment; it should be used only with
|
|
the function <tt>macroexpand</tt> for the sake of any local
|
|
macro definitions that the <tt>macrolet</tt> construct may have
|
|
established within that lexical environment. This is useful primarily
|
|
in the rare cases where a macro definition must explicitly expand any macros
|
|
in a subform of the macro call before computing its own expansion.
|
|
<P>
|
|
</DL>
|
|
See <tt>lambda-list-keywords</tt>.
|
|
<P>
|
|
|
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
|
<i>Notice of correction.</i>
|
|
In the first edition, the symbol <tt>&environment</tt> at the
|
|
left margin above was inadvertently omitted.
|
|
<P>
|
|
X3J13 voted in March 1989 (MACRO-ENVIRONMENT-EXTENT) <A NAME=8357> </A>
|
|
to specify that macro environment objects received with the <tt>&environment</tt>
|
|
argument of a macro function
|
|
have only dynamic extent. The consequences are undefined if such objects are
|
|
referred to outside the dynamic extent of that particular
|
|
invocation of the macro function.
|
|
This allows implementations to use somewhat more efficient techniques
|
|
for representing environment objects.
|
|
<P>
|
|
X3J13 voted in March 1989 (DEFMACRO-LAMBDA-LIST) <A NAME=8361> </A> to clarify the permitted
|
|
uses of <tt>&body</tt>, <tt>&whole</tt>, and <tt>&environment</tt>:
|
|
<UL><LI> <tt>&body</tt> may appear at any level of a <tt>defmacro</tt> lambda-list.<p>
|
|
<LI> <tt>&whole</tt> may appear at any level of a <tt>defmacro</tt> lambda-list.
|
|
At inner levels a <tt>&whole</tt> variable is bound to that part of the argument
|
|
that matches the sub-lambda-list in which <tt>&whole</tt> appears. No matter where
|
|
<tt>&whole</tt> is used, other parameters or lambda-list keywords may follow it.<p>
|
|
<LI> <tt>&environment</tt> may occur only at the outermost level of a <tt>defmacro</tt>
|
|
lambda-list, and it may occur at most once, but it may occur anywhere within
|
|
that lambda-list, even before an occurrence of <tt>&whole</tt>.
|
|
</UL>
|
|
<img align=bottom alt="change_end" src="gif/change_end.gif">
|
|
<P>
|
|
<tt>defmacro</tt>, unlike any other Common Lisp construct that has a lambda-list
|
|
as part of its syntax, provides an additional facility known as
|
|
<i>destructuring</i>.
|
|
<p>
|
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
|
See <tt>destructuring-bind</tt>, which provides the destructuring facility separately.
|
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
|
<P>
|
|
Anywhere in the lambda-list where a parameter
|
|
name may appear, and where ordinary lambda-list syntax (as described
|
|
in section <A HREF="node64.html#LAMBDAEXPRESSIONSSECTION">5.2.2</A>) does not
|
|
otherwise allow a list, a lambda-list may appear in place
|
|
of the parameter name. When this is done, then the argument form
|
|
that would match the parameter is treated as a (possibly dotted) list,
|
|
to be used as an argument forms list for satisfying the
|
|
parameters in the embedded lambda-list.
|
|
As an example, one could write the macro definition
|
|
for <tt>dolist</tt> in this manner:
|
|
<P><pre>
|
|
(defmacro dolist ((var listform <tt>&optional</tt> resultform)
|
|
&rest body)
|
|
...)
|
|
</pre><P>
|
|
More examples of embedded lambda-lists in <tt>defmacro</tt> are shown below.
|
|
<P>
|
|
Another destructuring rule is that <tt>defmacro</tt> allows any lambda-list
|
|
(whether top-level or embedded) to be dotted, ending
|
|
in a parameter name. This situation is treated exactly as if the
|
|
parameter name that ends the list had appeared preceded by <tt>&rest</tt>.
|
|
For example, the definition skeleton for <tt>dolist</tt> shown above could
|
|
instead have been written
|
|
<P><pre>
|
|
(defmacro dolist ((var listform &optional resultform)
|
|
. body)
|
|
...)
|
|
</pre><P>
|
|
<P>
|
|
If the compiler encounters a <tt>defmacro</tt>,
|
|
the new macro is added to the compilation
|
|
environment, and a compiled form of the expansion function is also added
|
|
to the output file so that the new macro will be operative at run time.
|
|
If this is not the desired effect, the <tt>defmacro</tt> form can be wrapped
|
|
in an <tt>eval-when</tt> construct.
|
|
<P>
|
|
It is permissible to use <tt>defmacro</tt> to redefine a macro
|
|
(for example, to install
|
|
a corrected version of an incorrect definition), or to redefine
|
|
a function as a macro.
|
|
It is an error to attempt to redefine the name of a special
|
|
form (see table <A HREF="node59.html#SPECIALFORMTABLE">5-1</A>) as a macro.
|
|
See <tt>macrolet</tt>, which establishes macro
|
|
definitions over a restricted lexical scope.
|
|
<P>
|
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
|
See also <tt>define-compiler-macro</tt>.
|
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
|
<P>
|
|
Suppose, for the sake of example, that it were desirable
|
|
to implement a conditional construct analogous to the
|
|
Fortran arithmetic IF statement. (This of course requires a certain
|
|
stretching of the imagination and suspension of disbelief.)
|
|
The construct should accept four forms: a <i>test-value</i>,
|
|
a <i>neg-form</i>, a <i>zero-form</i>, and a <i>pos-form</i>.
|
|
One of the last three forms is chosen to be executed according
|
|
to whether the value of the <i>test-form</i> is positive, negative,
|
|
or zero.
|
|
Using <tt>defmacro</tt>, a definition for such a construct
|
|
might look like this:
|
|
<P><pre>
|
|
(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)))))
|
|
</pre><P>
|
|
Note the use of the backquote facility in this definition
|
|
(see section <A HREF="node190.html#MACROCHARACTERSSECTION">22.1.3</A>).
|
|
Also note the use of <tt>gensym</tt> to generate a new variable name.
|
|
This is necessary to avoid conflict with any variables that might
|
|
be referred to in <i>neg-form</i>, <i>zero-form</i>, or <i>pos-form</i>.
|
|
<P>
|
|
If the form is executed by the interpreter, it will cause the
|
|
function definition of the symbol <tt>arithmetic-if</tt>
|
|
to be a macro associated with which is
|
|
a two-argument expansion function roughly equivalent to
|
|
<P><pre>
|
|
(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))))))
|
|
</pre><P>
|
|
The lambda-expression is produced by the <tt>defmacro</tt> declaration.
|
|
The calls to <tt>list</tt> are the (hypothetical) result of the backquote (<tt>`</tt>)
|
|
macro character and its associated commas.
|
|
The precise macro expansion function may depend on the implementation,
|
|
for example providing some degree of explicit error checking on the number
|
|
of argument forms in the macro call.
|
|
<P>
|
|
Now, if <tt>eval</tt> encounters
|
|
<P><pre>
|
|
(arithmetic-if (- x 4.0)
|
|
(- x)
|
|
(error "Strange zero")
|
|
x)
|
|
</pre><P>
|
|
this will be expanded into something like
|
|
<P><pre>
|
|
(let ((g407 (- x 4.0)))
|
|
(cond ((< g407 0) (- x))
|
|
((= g407 0) (error "Strange zero"))
|
|
(t x)))
|
|
</pre><P>
|
|
and <tt>eval</tt> tries again on this new form.
|
|
(It should be clear now that the backquote facility
|
|
is very useful in writing macros, since the form to be returned is
|
|
normally a complex list structure, typically consisting of a
|
|
mostly constant template with a few evaluated forms here and there.
|
|
The backquote template provides a ``picture'' of the resulting
|
|
code, with places to be filled in indicated by preceding commas.)
|
|
<P>
|
|
To expand on this example, stretching credibility to its limit,
|
|
we might allow the <i>pos-form</i>
|
|
and <i>zero-form</i> to be omitted, allowing their values to default to <tt>nil</tt>,
|
|
in much the same way that the <i>else</i> form of a Common Lisp <tt>if</tt> construct
|
|
may be omitted:
|
|
<P><pre>
|
|
(defmacro arithmetic-if (test neg-form
|
|
<tt>&optional</tt> zero-form pos-form)
|
|
(let ((var (gensym)))
|
|
`(let ((,var ,test))
|
|
(cond ((< ,var 0) ,neg-form)
|
|
((= ,var 0) ,zero-form)
|
|
(t ,pos-form)))))
|
|
</pre><P>
|
|
Then one could write
|
|
<P><pre>
|
|
(arithmetic-if (- x 4.0) (print x))
|
|
</pre><P>
|
|
which would be expanded into something like
|
|
<P><pre>
|
|
(let ((g408 (- x 4.0)))
|
|
(cond ((< g408 0) (print x))
|
|
((= g408 0) nil)
|
|
(t nil)))
|
|
</pre><P>
|
|
The resulting code is correct but rather silly-looking.
|
|
One might rewrite the macro definition to produce better code
|
|
when <i>pos-form</i> and possibly <i>zero-form</i> are omitted,
|
|
or one might simply rely on the Common Lisp implementation to provide
|
|
a compiler smart enough to improve the code itself.
|
|
<P>
|
|
Destructuring is a very powerful facility that allows
|
|
the <tt>defmacro</tt> lambda-list to express the structure of
|
|
a complicated macro-call syntax. If no lambda-list keywords
|
|
appear, then the <tt>defmacro</tt> lambda-list is simply a list,
|
|
nested to some extent, containing parameter names at the leaves.
|
|
The macro-call form must have the same list structure.
|
|
For example, consider this macro definition:
|
|
<P><pre>
|
|
(defmacro halibut ((mouth eye1 eye2)
|
|
((fin1 length1) (fin2 length2))
|
|
tail)
|
|
...)
|
|
</pre><P>
|
|
Now consider this macro call:
|
|
<P><pre>
|
|
(halibut (m (car eyes) (cdr eyes))
|
|
((f1 (count-scales f1)) (f2 (count-scales f2)))
|
|
my-favorite-tail)
|
|
</pre><P>
|
|
This would cause the expansion function to receive the following
|
|
values for its parameters:
|
|
<pre>
|
|
Parameter Value
|
|
---------------------------------
|
|
mouth m
|
|
eye1 (car eyes)
|
|
eye2 (cdr eyes)
|
|
fin1 f1
|
|
length1 (count-scales f1)
|
|
fin2 f2
|
|
length2 (count-scales f2)
|
|
tail my-favorite-tail
|
|
---------------------------------
|
|
</pre>
|
|
The following macro call would be in error because there would be no
|
|
argument form to match the parameter <tt>length1</tt>:
|
|
<P><pre>
|
|
(halibut (m (car eyes) (cdr eyes))
|
|
((f1) (f2 (count-scales f2)))
|
|
my-favorite-tail)
|
|
</pre><P>
|
|
The following macro call would be in error because a symbol appears
|
|
in the call where the structure of the lambda-list requires a list.
|
|
<P><pre>
|
|
(halibut my-favorite-head
|
|
((f1 (count-scales f1)) (f2 (count-scales f2)))
|
|
my-favorite-tail)
|
|
</pre><P>
|
|
The fact that the value of the variable <tt>my-favorite-head</tt>
|
|
might happen to be a list is irrelevant here. It is the macro call
|
|
itself whose structure must match that of the <tt>defmacro</tt> lambda-list.
|
|
<P>
|
|
The use of lambda-list keywords adds even greater flexibility.
|
|
For example, suppose it is convenient within the expansion
|
|
function for <tt>halibut</tt> to be able to refer to the list
|
|
whose components are called <tt>mouth</tt>, <tt>eye1</tt>, and <tt>eye2</tt> as <tt>head</tt>.
|
|
One may write this:
|
|
<P><pre>
|
|
(defmacro halibut ((<tt>&whole</tt> head mouth eye1 eye2)
|
|
((fin1 length1) (fin2 length2))
|
|
tail)
|
|
</pre><P>
|
|
Now consider the same valid macro call as before:
|
|
<P><pre>
|
|
(halibut (m (car eyes) (cdr eyes))
|
|
((f1 (count-scales f1)) (f2 (count-scales f2)))
|
|
my-favorite-tail)
|
|
</pre><P>
|
|
This would cause the expansion function to receive the same
|
|
values for its parameters and also a value for the parameter <tt>head</tt>:
|
|
<pre>
|
|
Parameter Value
|
|
------------------------------------------
|
|
head (m (car eyes) (cdr eyes))
|
|
------------------------------------------
|
|
</pre>
|
|
The stipulation that
|
|
an embedded lambda-list is permitted only
|
|
where ordinary lambda-list syntax would permit a parameter name
|
|
but not a list is made to prevent ambiguity. For example,
|
|
one may not write
|
|
<P><pre>
|
|
(defmacro loser (x <tt>&optional</tt> (a b <tt>&rest</tt> c) <tt>&rest</tt> z)
|
|
...)
|
|
</pre><P>
|
|
because ordinary lambda-list syntax does permit a list following <tt>&optional</tt>;
|
|
the list <tt>(a b <tt>&rest</tt> c)</tt> would be interpreted as describing an
|
|
optional parameter named <tt>a</tt> whose default value is that of the
|
|
form <tt>b</tt>, with a supplied-p parameter named <tt>&rest</tt> (not legal),
|
|
and an extraneous symbol <tt>c</tt> in the list (also not legal). An almost
|
|
correct way to express this is
|
|
<P><pre>
|
|
(defmacro loser (x <tt>&optional</tt> ((a b <tt>&rest</tt> c)) <tt>&rest</tt> z)
|
|
...)
|
|
</pre><P>
|
|
The extra set of parentheses removes the ambiguity. However, the
|
|
definition is now incorrect because a macro call such as <tt>(loser (car pool))</tt>
|
|
would not provide any argument form for the lambda-list <tt>(a b <tt>&rest</tt> c)</tt>,
|
|
and so the default value against which to match the lambda-list would be
|
|
<tt>nil</tt> because no explicit default value was specified. This is in error
|
|
because <tt>nil</tt> is an empty list; it does not have forms to satisfy the
|
|
parameters <tt>a</tt> and <tt>b</tt>. The fully correct definition would be either
|
|
<P><pre>
|
|
(defmacro loser (x <tt>&optional</tt> ((a b <tt>&rest</tt> c) '(nil nil)) <tt>&rest</tt> z)
|
|
...)
|
|
</pre><P>
|
|
or
|
|
<P><pre>
|
|
(defmacro loser (x <tt>&optional</tt> ((<tt>&optional</tt> a b <tt>&rest</tt> c)) <tt>&rest</tt> z)
|
|
...)
|
|
</pre><P>
|
|
These differ slightly: the first requires that if the macro call
|
|
specifies <tt>a</tt> explicitly then it must also specify <tt>b</tt> explicitly,
|
|
whereas the second does not have this requirement. For example,
|
|
<P><pre>
|
|
(loser (car pool) ((+ x 1)))
|
|
</pre><P>
|
|
would be a valid call for the second definition but not for the first.
|
|
<P>
|
|
<BR> <HR><A NAME=tex2html2746 HREF="node99.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html2744 HREF="node97.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html2738 HREF="node97.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html2748 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html2749 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
|
<B> Next:</B> <A NAME=tex2html2747 HREF="node99.html"> Macro Expansion</A>
|
|
<B>Up:</B> <A NAME=tex2html2745 HREF="node97.html"> Macros</A>
|
|
<B> Previous:</B> <A NAME=tex2html2739 HREF="node97.html"> Macros</A>
|
|
<HR> <P>
|
|
<HR>
|
|
<P><ADDRESS>
|
|
AI.Repository@cs.cmu.edu
|
|
</ADDRESS>
|
|
</BODY>
|