Macros 宏观膨胀下特殊变量的行为
我关于宏观扩张的思维模式(显然是错误的)说,以下情况按顺序发生: 运行Macros 宏观膨胀下特殊变量的行为,macros,common-lisp,special-variables,Macros,Common Lisp,Special Variables,我关于宏观扩张的思维模式(显然是错误的)说,以下情况按顺序发生: 运行bot的宏扩展(将*foo*绑定到17),运行bar的宏扩展,它打印*foo*的当前值(即17),并返回表单(+1 1),该表单不是宏,宏扩展时间现已结束,最后计算表单(+1 1),并返回2 为什么我错了 有没有一种简单的方法可以实现我的目的?当REPL被告知评估(bot),它首先必须执行宏扩展。它调用宏扩展函数bot,这实际上意味着 FUZZ> (defvar *foo* nil) *FOO* FUZZ> (de
bot
的宏扩展(将*foo*
绑定到17
),运行bar
的宏扩展,它打印*foo*
的当前值(即17
),并返回表单(+1 1)
,该表单不是宏,宏扩展时间现已结束,最后计算表单(+1 1)
,并返回2
为什么我错了
有没有一种简单的方法可以实现我的目的?当REPL被告知评估
(bot)
,它首先必须执行宏扩展。它调用宏扩展函数bot
,这实际上意味着
FUZZ> (defvar *foo* nil)
*FOO*
FUZZ> (defmacro bar ()
(format t "foo: ~A" *foo*)
`(+ 1 1))
BAR
FUZZ> (defmacro bot ()
(let ((*foo* 17))
`(bar)))
BOT
FUZZ> (bot)
foo: NIL
它返回(bar)
,然后fromlet
的绑定被解除。现在我们有了(条)
bar
是一个宏,所以现在是进行下一轮宏扩展的时候了,这意味着
(let ((*foo* 17))
`(bar))
它打印foo:NIL
,并返回(+1)
如果希望在某些绑定的范围内执行宏扩展,则需要自己调用宏扩展函数。例如,您可以使用:
但是,如果你打算自己进行宏观扩张,一定要保留。在这种情况下,baz
的更好定义是:
CL-USER> (defparameter *foo* nil)
*FOO*
CL-USER> (defmacro bar ()
(format t "foo: ~a" *foo*)
`(+ 1 1))
BAR
CL-USER> (defmacro baz ()
(let ((*foo* 42))
(macroexpand '(bar))))
BAZ
CL-USER> (baz)
foo: 42
2
啊哈,所以我的错误是把
*foo*
的绑定看作一个动态变量,在宏扩展(bar)
和(关键的)它依次变成的所有形式所花费的所有时间里都是有效的。事实上,一旦(bar)
被返回,我们就完成了*foo*
,正如约书亚所说的那样。。。
CL-USER> (defparameter *foo* nil)
*FOO*
CL-USER> (defmacro bar ()
(format t "foo: ~a" *foo*)
`(+ 1 1))
BAR
CL-USER> (defmacro baz ()
(let ((*foo* 42))
(macroexpand '(bar))))
BAZ
CL-USER> (baz)
foo: 42
2
(defmacro baz (&environment env)
(let ((*foo* 42))
(macroexpand '(bar) env)))