A DEFMACRO form looks a lot like a DEFUN
form (see Lesson 7) -- it has a name, a
list of argument names, and a body:
(defmacro name (argument ...) body)
The macro body returns a form to be evaluated. In other words, you need to write the body of the macro such that it returns a form, not a value. When Lisp evaluates a call to your macro, it first evaluates the body of your macro definition, then evaluates the result of the first evaluation. (By way of comparison, a function's body is evaluated to return a value.)
Here are a couple of simple macros to illustrate most of what you need to know:
(defmacro setq-literal (place literal) `(setq ,place ',literal))
SETQ-LITERAL
(setq-literal a b)
B
a
B
(defmacro reverse-cons (rest first) `(cons ,first ,rest))
REVERSE-CONS
(reverse-cons nil A)
(B)
SETQ-LITERAL works like SETQ, except that
neither argument is evaluated. (Remember that SETQ
evaluates its second argument.) The body of SETQ-LITERAL has
a form that begins with a ` (pronounced "backquote").
Backquote behaves like quote -- suppressing evaluation of all the enclosed
forms -- except where a comma appears within the backquoted form. A
symbol following the comma is evaluated.
So in our call to (SETQ-LITERAL A B) above, here's what
happens:
PLACE to the symbol A.LITERAL to the symbol B.`(SETQ ,PLACE ',LITERAL), following
these steps:PLACE to get the symbol A.LITERAL to get the symbol B.(SETQ A 'B).(SETQ A 'B).Neither the backquote nor the commas appear in the returned form.
Neither A nor B is evaluated in a call to
SETQ-LITERAL, but for different reasons. A is
unevaluated because it appears as the first argument of
SETQ. B is unevaluated because it appears after
a quote in the form returned by the macro.
The operation of (REVERSE-CONS NIL A) is similar:
RESTNIL.
FIRST to the symbol A.`(CONS ,FIRST ,REST), following these
steps:FIRST to get the symbol A.REST to get the symbol NIL.(CONS A NIL).(CONS A NIL).Both arguments of REVERSE-CONS are evaluated because
CONS evaluates its arguments, and our macro body doesn't quote
either argument. A evaluates to the symbol B, and
NIL evaluates to itself.
If you want to see how your macro body appears before evaluation, you
can use the MACROEXPAND function:
(macroexpand '(setq-literal a b))
(SETQ A 'B)
(macroexpand '(reverse-cons nil a))
(CONS A NIL)
Since MACROEXPAND is a function, it evaluates its
arguments. This is why you have to quote the form you want expanded.
The examples in this lesson are deliberately very simple, so you can understand the basic mechanism. In general, macros are trickier to write than functions -- in Chapter 20 we'll look at the reasons and the correct techniques for dealing with more complex situations.