考虑 Common Lisp 中的以下形式序列(在 Windows 的 SBCL 2.4.2 中执行评估):
(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
有人可以帮助我理解为什么第二和第三种形式评估出不同的结果吗?
我预计第二和第三种形式会得到相同的结果。
问题:您将尝试在错误的环境中扩展宏。
macrolet
定义了本地宏,但macroexpand-1
看不到它。
CL-USER 23 > (defmacro expand-1-form (form &environment env)
(list 'quote (macroexpand-1 form env)))
EXPAND-1-FORM
上面定义了一个宏,它传递当前环境,然后可以通过变量
env
使用。该宏使用 macroexpand-1
扩展了这种形式,并将环境传递给它。扩展以引用形式返回。
现在我们可以使用宏
double-l
来扩展本地宏expand-1-form
:
CL-USER 24 > (macrolet ((double-l (x) (list (quote +) x x)))
(expand-1-form (double-l 3)))
(+ 3 3)
上面扩展了宏expand-1-form,传递当前环境。然后用该环境调用
macroexpand-1
。