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.