Common Lisp HyperSpec 讨论了什么是环境。它还讨论了“环境对象”并告诉我们它们的本质是依赖于实现的。有些函数,如 MACROEXPAND,采用可选的环境对象参数。 我找不到的是如何实际获取环境对象或修改它,或者如何实际使用它的示例。
MACROEXPAND 页面中的示例都没有环境对象,甚至那些涉及词法环境的示例也没有 - 这些示例都使用 MACROLET。 Common Lisp 语言,第二版 有一个 AUGMENT-ENVIRONMENT 函数,但显然这不在标准中。 有没有可以真正获取和操作环境的函数?如果不是,为什么像 MACROEXPAND 这样的函数需要一个环境参数?我看到了
这个先前的问题defmacro
定义宏,那么您可以使用
&environment
lambda-list 关键字获取该值。像 macroexpand
和
macro-function
这样的东西采用环境参数并使用它们来了解例如是否在词法环境中定义了宏。如果您想编写代码步行器,这是至关重要的,例如:您需要知道在当前词法环境中,表单是否引用宏,如果是,则扩展它。这是一个显示此工作原理的示例(尽管以一种相当愚蠢的方式):
(defmacro mf (name &environment e)
(if (macro-function name e)
`(format t "~&~S denotes a macro~%" ',name)
`(format t "~&~S does not denotes a macro~%" ',name)))
(defun ts1 ()
(mf foo))
(defun ts2 ()
(macrolet ((foo (&body forms)
`(progn ,@forms)))
(mf foo)))
现在
> (ts1)
foo does not denotes a macro
nil
> (ts2)
foo denotes a macro
nil
更常见的用法是
constantp
:这告诉您给定的形式在求值时是否是常量。
constantp
可以传递一个环境对象,并且可以利用该对象来确定形式在该环境中是否恒定。 constantp
不需要使用该环境,但显然可以。在 CL 的标准化过程中,有一个相当实质性的提案,要求围绕环境对象制定更丰富的协议:该提案被撤回,因为人们认为还没有准备好标准化。您可以在 CLHS here