Subject: Re: Macros
From: Erik Naggum <erik@naggum.no>
Date: 11 Aug 2002 23:38:11 +0000
Newsgroups: comp.lang.lisp
Message-ID: <3238097891764805@naggum.no>
* Thomas Stegen CES2000
| Is using a macro the same as returning a form from a function and using eval
| on that form?
Not precisely correct, but pretty close. A macro invocation is replaced by
the return value from the macro (expansion) function, and this would, when
evaluated or compiled, retain the lexical environment of the form. If you
have used a macro in a different setting, which is certainly possible, you
would find that it would not necessarily be evaluated.
| Are the following two forms semantically equivalent?
Yes, but this is a very special case that probably only confuses you.
| They return the same result, but is there some subtle difference somewhere?
Well, yes, the call to `eval´. :)
| What about in the general case?
In the general case, a macro is called when encountered in the recursive
evaluation of each argument. Recall that `eval´ is a recursive function
that effectively does (funcall (car form) (mapcar #'eval (cdr form))) for a
function call. For this to work properly, the innermost `eval´ call must
return a form that works in the environment of the next outer `eval´. For
this to work, the macro function stored in the function slot of a macro
takes two parameters, the whole macro form and the environment in which it
is to be understood. This is not entirely trivial to explain, since the
environment has to be queried to find the macro expansion function.
You can try this, instead
(let ((form '(madd)))
(funcall (macro-function (car form)) form nil))
| And one more question. When is a macro expanded?
When the form is about to acquire its meaning in the compiler or interpreter
as defined by the language. This need not necessarily lead to evaluation
right away, but sooner or later it normally will. At issue is how late this
happens and how much environmental baggage the evaluation requires.
In general, a macro is called with all the information that the enclosing
forms present to the expander. This is much more than just `eval´ does.
I think the best way to understand macros is to study an implementation of
`eval´. Using the traditional Scheme textbooks and exercies for this will
work, if you remember that a macro call is replaced by its return value and
then re-interpreted as if the return value was the original form and that
this does not mean immediate evaluation, except insofar as the macro
function has side-effects. (E.g., it could perform some book-keeping.)
--
Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.