8.2 Macro Expansion

The macroexpand function is the conventional means for expanding a macro call. A hook is provided for a user function to gain control during the expansion process.

[Function] macroexpand form &optional env
[Function] macroexpand-1 form &optional env

If form is a macro call, then macroexpand-1 will expand the macro call once and return two values: the expansion and t. If form is not a macro call, then the two values form and nil are returned.

A form is considered to be a macro call only if it is a cons whose car is a symbol that names a macro. The environment env is similar to that used within the evaluator (see evalhook); it defaults to a null environment. Any local macro definitions established within env by macrolet will be considered. If only form is given as an argument, then the environment is effectively null, and only global macro definitions (as established by defmacro) will be considered.

Macro expansion is carried out as follows. Once macroexpand-1 has determined that a symbol names a macro, it obtains the expansion function for that macro. The value of the variable *macroexpand-hook* is then called as a function of three arguments: the expansion function, the form, and the environment env. The value returned from this call is taken to be the expansion of the macro call. The initial value of *macroexpand-hook* is funcall, and the net effect is to invoke the expansion function, giving it form and env as its two arguments.

X3J13 voted in June 1988 to specify that the value of *macroexpand-hook* is first coerced to a function before being called as the expansion interface hook. Therefore its value may be a symbol, a lambda-expression, or any object of type function.

X3J13 voted in March 1989 to specify that macro environment objects received by a *macroexpand-hook* function have only dynamic extent. The consequences are undefined if such objects are referred to outside the dynamic extent of that particular invocation of the hook function. This allows implementations to use somewhat more efficient techniques for representing environment objects.

X3J13 voted in June 1989 to clarify that, while *macroexpand-hook* may be useful for debugging purposes, despite the original design intent there is currently no correct portable way to use it for caching macro expansions.

X3J13 also noted that, although there seems to be no correct portable way to use *macroexpand-hook* to cache macro expansions, there is no requirement that an implementation call the macro expansion function more than once for a given form and lexical environment.

X3J13 voted in March 1989 to specify that macroexpand-1 will also expand symbol macros defined by symbol-macrolet; therefore a form may also be a macro call if it is a symbol. The vote did not address the interaction of this feature with the *macroexpand-hook* function. An obvious implementation choice is that the hook function is indeed called and given a special expansion function that, when applied to the form (a symbol) and env, will produce the expansion, just as for an ordinary macro; but this is only my suggestion.

The evaluator expands macro calls as if through the use of macroexpand-1; the point is that eval also uses *macroexpand-hook*.

macroexpand is similar to macroexpand-1, but repeatedly expands form until it is no longer a macro call. (In effect, macroexpand simply calls macroexpand-1 repeatedly until the second value returned is nil.) A second value of t or nil is returned as for macroexpand-1, indicating whether the original form was a macro call.


[Variable] *macroexpand-hook*

The value of *macroexpand-hook* is used as the expansion interface hook by macroexpand-1.