137 lines
13 KiB
HTML
137 lines
13 KiB
HTML
<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>CLHS: Macro DEFMACRO</TITLE>
|
|
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
|
|
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
|
|
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
|
|
<LINK REL=TOP HREF="../Front/index.htm">
|
|
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
|
|
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
|
|
<LINK REL=PREV HREF="m_define.htm">
|
|
<LINK REL=UP HREF="c_evalua.htm">
|
|
<LINK REL=NEXT HREF="f_macro_.htm">
|
|
</HEAD>
|
|
<BODY>
|
|
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="m_define.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="c_evalua.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="f_macro_.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
|
|
|
|
<HR>
|
|
|
|
<A NAME="defmacro"><I>Macro</I> <B>DEFMACRO</B></A> <P>
|
|
<P>
|
|
<P><B>Syntax:</B><P>
|
|
<P>
|
|
|
|
<B>defmacro</B> <I>name lambda-list [[<I>declaration</I><B>*</B> | <I>documentation</I>]] <I>form</I><B>*</B></I><P> => <I>name</I><P>
|
|
<P>
|
|
<P><B>Arguments and Values:</B><P>
|
|
<P>
|
|
<I>name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <I>lambda-list</I>---a <A REL=DEFINITION HREF="26_glo_m.htm#macro_lambda_list"><I>macro lambda list</I></A>. <P>
|
|
<I>declaration</I>---a <A REL=DEFINITION HREF="s_declar.htm#declare"><B>declare</B></A> <A REL=DEFINITION HREF="26_glo_e.htm#expression"><I>expression</I></A>; not evaluated. <P>
|
|
<I>documentation</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#string"><I>string</I></A>; not evaluated. <P>
|
|
<I>form</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. <P>
|
|
<P><B>Description:</B><P>
|
|
<P>
|
|
Defines <I>name</I> as a <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A> by associating a <A REL=DEFINITION HREF="26_glo_m.htm#macro_function"><I>macro function</I></A> with that <I>name</I> in the global environment. The <A REL=DEFINITION HREF="26_glo_m.htm#macro_function"><I>macro function</I></A> is defined in the same <A REL=DEFINITION HREF="26_glo_l.htm#lexical_environment"><I>lexical environment</I></A> in which the <A REL=DEFINITION HREF="#defmacro"><B>defmacro</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> appears. <P>
|
|
The parameter variables in <I>lambda-list</I> are bound to destructured portions of the macro call. <P>
|
|
The expansion function accepts two arguments, a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> and an <A REL=DEFINITION HREF="26_glo_e.htm#environment"><I>environment</I></A>. The expansion function returns a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. The body of the expansion function is specified by <I>forms</I>. <I>Forms</I> are executed in order. The value of the last <I>form</I> executed is returned as the expansion of the <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A>. The body <I>forms</I> of the expansion function (but not the <I>lambda-list</I>) are implicitly enclosed in a <A REL=DEFINITION HREF="26_glo_b.htm#block"><I>block</I></A> whose name is <I>name</I>. <P>
|
|
The <I>lambda-list</I> conforms to the requirements described in <A REL=CHILD HREF="03_dd.htm">Section 3.4.4 (Macro Lambda Lists)</A>. <P>
|
|
<I>Documentation</I> is attached as a <A REL=DEFINITION HREF="26_glo_d.htm#documentation_string"><I>documentation string</I></A> to <I>name</I> (as kind <A REL=DEFINITION HREF="s_fn.htm#function"><B>function</B></A>) and to the <A REL=DEFINITION HREF="26_glo_m.htm#macro_function"><I>macro function</I></A>. <P>
|
|
<A REL=DEFINITION HREF="#defmacro"><B>defmacro</B></A> can be used to redefine a <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A> or to replace a <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> definition with a <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A> definition. <P>
|
|
Recursive expansion of the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> returned must terminate, including the expansion of other <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macros</I></A> which are <A REL=DEFINITION HREF="26_glo_s.htm#subform"><I>subforms</I></A> of other <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A> returned. <P>
|
|
The consequences are undefined if the result of fully macroexpanding a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> contains any <A REL=DEFINITION HREF="26_glo_c.htm#circular"><I>circular</I></A> <A REL=DEFINITION HREF="26_glo_l.htm#list_structure"><I>list structure</I></A> except in <A REL=DEFINITION HREF="26_glo_l.htm#literal"><I>literal</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>objects</I></A>. <P>
|
|
If a <A REL=DEFINITION HREF="#defmacro"><B>defmacro</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> appears as a <A REL=DEFINITION HREF="26_glo_t.htm#top_level_form"><I>top level form</I></A>, the <A REL=DEFINITION HREF="26_glo_c.htm#compiler"><I>compiler</I></A> must store the <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A> 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 <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A> can be evaluated at compile time if it is referenced within the <A REL=DEFINITION HREF="26_glo_f.htm#file"><I>file</I></A> being <I>compiled</I>. <P>
|
|
<P><B>Examples:</B><P>
|
|
<P>
|
|
<PRE>
|
|
(defmacro mac1 (a b) "Mac1 multiplies and adds"
|
|
`(+ ,a (* ,b 3))) => MAC1
|
|
(mac1 4 5) => 19
|
|
(documentation 'mac1 'function) => "Mac1 multiplies and adds"
|
|
(defmacro mac2 (&optional (a 2 b) (c 3 d) &rest x) `'(,a ,b ,c ,d ,x)) => MAC2
|
|
(mac2 6) => (6 T 3 NIL NIL)
|
|
(mac2 6 3 8) => (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)) => MAC3
|
|
(mac3 1 6 :d 8 :c 9 :d 10) => ((MAC3 1 6 :D 8 :C 9 :D 10) 1 6 9 8 (:D 8 :C 9 :D 10))
|
|
</PRE>
|
|
</TT> <P>
|
|
The stipulation that an embedded <A REL=DEFINITION HREF="26_glo_d.htm#destructuring_lambda_list"><I>destructuring lambda list</I></A> is permitted only where <A REL=DEFINITION HREF="26_glo_o.htm#ordinary_lambda_list"><I>ordinary lambda list</I></A> syntax would permit a parameter name but not a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> is made to prevent ambiguity. For example, the following is not valid: <P>
|
|
<PRE>
|
|
(defmacro loser (x &optional (a b &rest c) &rest z)
|
|
...)
|
|
</PRE>
|
|
</TT> because <A REL=DEFINITION HREF="26_glo_o.htm#ordinary_lambda_list"><I>ordinary lambda list</I></A> syntax does permit a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> following <TT>&optional</TT>; the list <TT>(a b &rest 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 valid), and an extraneous symbol <TT>c</TT> in the list (also not valid). An almost correct way to express this is <P>
|
|
<PRE>
|
|
(defmacro loser (x &optional ((a b &rest c)) &rest z)
|
|
...)
|
|
</PRE>
|
|
</TT> 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 &rest c)</TT>, and so the default value against which to match the <A REL=DEFINITION HREF="26_glo_l.htm#lambda_list"><I>lambda list</I></A> would be <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> because no explicit default value was specified. The consequences of this are unspecified since the empty list, <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>, does not have <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A> to satisfy the parameters <TT>a</TT> and <TT>b</TT>. The fully correct definition would be either <P>
|
|
<PRE>
|
|
(defmacro loser (x &optional ((a b &rest c) '(nil nil)) &rest z)
|
|
...)
|
|
</PRE>
|
|
</TT> or <P>
|
|
<PRE>
|
|
(defmacro loser (x &optional ((&optional a b &rest c)) &rest z)
|
|
...)
|
|
</PRE>
|
|
</TT> 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>
|
|
</TT> would be a valid call for the second definition but not for the first. <P>
|
|
<P>
|
|
<PRE>
|
|
(defmacro dm1a (&whole x) `',x)
|
|
(macroexpand '(dm1a)) => (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)) => (QUOTE ((DM1B Q) Q NIL))
|
|
(macroexpand '(dm1b q r)) => (QUOTE ((DM1B Q R) Q R))
|
|
(macroexpand '(dm1b q r s)) is an error.
|
|
</PRE>
|
|
</TT> <P>
|
|
<PRE>
|
|
(defmacro dm2a (&whole form a b) `'(form ,form a ,a b ,b))
|
|
(macroexpand '(dm2a x y)) => (QUOTE (FORM (DM2A X Y) A X B Y))
|
|
(dm2a x y) => (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))
|
|
=> (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)))
|
|
=> ((DM2B X1 (((SEGUNDO X2) X3 X4)) X5 X6)
|
|
5 (((SEGUNDO X2) X3 X4)) (CADR X2) (X3 X4) 5 (X5 X6))
|
|
</PRE>
|
|
</TT> <P>
|
|
<P>
|
|
<P><B>Affected By:</B> None.
|
|
<P>
|
|
<P><B>Exceptional Situations:</B> None.
|
|
<P>
|
|
<P><B>See Also:</B><P>
|
|
<P>
|
|
<A REL=DEFINITION HREF="m_define.htm#define-compiler-macro"><B>define-compiler-macro</B></A>, <A REL=DEFINITION HREF="m_destru.htm#destructuring-bind"><B>destructuring-bind</B></A>, <A REL=DEFINITION HREF="f_docume.htm#documentation"><B>documentation</B></A>, <A REL=DEFINITION HREF="f_mexp_.htm#macroexpand"><B>macroexpand</B></A>, <A REL=DEFINITION HREF="v_mexp_h.htm#STmacroexpand-hookST"><B>*macroexpand-hook*</B></A>, <A REL=DEFINITION HREF="s_flet_.htm#macrolet"><B>macrolet</B></A>, <A REL=DEFINITION HREF="f_macro_.htm#macro-function"><B>macro-function</B></A>, <A REL=CHILD HREF="03_a.htm">Section 3.1 (Evaluation)</A>, <A REL=CHILD HREF="03_b.htm">Section 3.2 (Compilation)</A>, <A REL=CHILD HREF="03_dk.htm">Section 3.4.11 (Syntactic Interaction of Documentation Strings and Declarations)</A> <P>
|
|
<P><B>Notes:</B> None.
|
|
<P>
|
|
<P>
|
|
<P><HR>The following <A REL=META HREF="../Front/X3J13Iss.htm">X3J13 cleanup issues</A>, <I>not part of the specification</I>, apply to this section:<P><UL><LI> <A REL=CHILD HREF="../Issues/iss101.htm">DEFINE-COMPILER-MACRO:X3J13-NOV89</A><LI> <A REL=CHILD HREF="../Issues/iss106.htm">DEFMACRO-LAMBDA-LIST:TIGHTEN-DESCRIPTION</A><LI> <A REL=CHILD HREF="../Issues/iss059.htm">COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY</A><LI> <A REL=CHILD HREF="../Issues/iss291.htm">RECURSIVE-DEFTYPE:EXPLICITLY-VAGUE</A><LI> <A REL=CHILD HREF="../Issues/iss135.htm">DOCUMENTATION-FUNCTION-BUGS:FIX</A><LI> <A REL=CHILD HREF="../Issues/iss105.htm">DEFMACRO-BLOCK-SCOPE:EXCLUDES-BINDINGS</A><LI> <A REL=CHILD HREF="../Issues/iss161.htm">FLET-IMPLICIT-BLOCK:YES</A><LI> <A REL=CHILD HREF="../Issues/iss104.htm">DEFINING-MACROS-NON-TOP-LEVEL:ALLOW</A><LI> <A REL=CHILD HREF="../Issues/iss097.htm">DECLS-AND-DOC</A><P></UL><HR>
|
|
|
|
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
|
|
|
|
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
|
|
</BODY>
|
|
</HTML>
|