[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lexical references in DEFMACRO



    Date: Friday, 2 May 1986  19:27-EDT
    From: edsel!sunvalleymall!eb at su-navajo.arpa (Eric Benson)
    Re:   Lexical references in DEFMACRO

    The Common Lisp definition continues to surprise me.  I had not
    noticed that DEFMACRO is not allowed to let its body refer to any
    lexically visible entities outside the DEFMACRO form.  On the other
    hand, DEFUN is specifically allowed to refer to lexically visible
    entities.  This deserves some explanation.  It seems I am allowed to
    do this:

    (LET ((SOME-DATA-STRUCTURE (MAKE-SOME-DATA-STRUCTURE)))
      (DEFUN SOME-FUNCTION ()
        (DO-SOMETHING-WITH SOME-DATA-STRUCTURE)))

    but not this:

    (LET ((SOME-DATA-STRUCTURE (MAKE-SOME-DATA-STRUCTURE)))
      (DEFMACRO SOME-MACRO ()
        (MAKE-A-FORM-WITH SOME-DATA-STRUCTURE)))

    To do what I want in the second case I must do this:

    (LET ((SOME-DATA-STRUCTURE (MAKE-SOME-DATA-STRUCTURE)))
      (SETF (MACRO-FUNCTION 'SOME-MACRO)
    	#'(LAMBDA (FORM ENVIRONMENT
    	    (DECLARE (IGNORE FORM ENVIRONMENT))
    	    (MAKE-A-FORM-WITH SOME-DATA-STRUCTURE)))))

    Furthermore, in order to implement this restriction I must introduce a
    new special form, such as that used in Spice Lisp, to force a form to
    be evaluated in the null lexical environment.  Thus it is impossible
    to live up to the suggestion in the implementation note on p.58, that
    macros should not expand into implementation-dependent special forms.

This is a good point which I overlooked.  It looks like this special
form must become a part of the language, not because users need to use
it directly, but becuase some macros must expand into it.

    It is obvious to me why the expansion functions defined by MACROLET
    must have this restriction; there is no environment at macroexpansion
    time to which they can refer.  The expansion functions created by
    DEFMACRO, on the other hand, are not really very different from
    ordinary functions created by DEFUN.

    There is one difference, but it is outside the scope of the Common
    Lisp definition.  Most (i.e. all) implementations of Common Lisp cause
    macros defined by DEFMACRO to be available for use while compiling the
    file in which they are defined.  This is not required by the Common
    Lisp definition, but is part of the Lisp tradition.

This is not true, see the bottom of p146 "If the compiler encounters a
DEFMACRO..."  It seems pretty clear that this *must* be part of the
definition, since the programmer must make sure that her macros are
defined before she uses them.  If you require an explicit EVAL-WHEN,
then nearly every program I have ever written would have to be changed.

    It should be obvious that this is only possible for macro
    definitions which occur at "top level."  For example, it would be
    incorrect in this example to define THIS-MACRO at compile time:

    (WHEN SOME-CONDITION
          (DEFMACRO THIS-MACRO ()
    	(EXPAND-INTO-SOMETHING)))

In my previous discussion of "top level forms", I explained why I also
don't agree with this.  The notion of a "top level form" just doesn't
belong in a lexical Lisp.  Implicit compiler evaluation such as
putting DEFMACRO definitions in the compiler environment should happen
no matter where the form appears.

    Similarly, any macro definition which refers to a lexically visible
    entity cannot be defined at compile time, since it cannot be a "top
    level" form.

It seems to me that you are arguing much more effectively for the null
DEFMACRO environment than you are arguing against the implicit
evaluation.  It is clear that they are mutually exclusive.

  Rob