Consider the following sequence of forms in Common Lisp (evaluations performed in SBCL 2.4.2 for Windows):
(defmacro double-g (x)
(list (quote +) x x))
(macroexpand-1 (quote (double-g 3))) => (+ 3 3), T
(macrolet ((double-l (x) (list (quote +) x x)))
(macroexpand-1 (quote (double-l 3))))
=> (DOUBLE-L 3), NIL
Can someone help me understand why the second and third forms evaluate to different results?
I expected the second and third forms to evaluate to the same result.
Problem: you are trying to expand the macro in the wrong environment. The
macroletdefines a local macro, butmacroexpand-1does not see it, because it does not get the lexical environment passed.We'll modify the macro expander:
Above defines a macro
expand-1-form, which gets passed the current environment, which then is available via the variableenv. The macro expands this form by usingmacroexpand-1and also passes the environment to it. The macroexpand-1-formgets the environment automagically passed into the environment variableenv(which we defined in the parameter list). The expansion is returned as a quoted form.Now we can expand the local macro
double-lusing the macroexpand-1-form:Above expands the macro
expand-1-form, passing the current environment. This then callsmacroexpand-1with that environment.We can also write it as nested
macrolets: