Common lisp 何谓&;公共Lisp中的环境?
我对common lisp中的&environment参数感到困惑。特别是,它的用途是什么?为什么它是一个参数,而不是一个特殊变量 编辑:如果能看到一个具体的例子,说明如何在代码中使用Common lisp 何谓&;公共Lisp中的环境?,common-lisp,environment,Common Lisp,Environment,我对common lisp中的&environment参数感到困惑。特别是,它的用途是什么?为什么它是一个参数,而不是一个特殊变量 编辑:如果能看到一个具体的例子,说明如何在代码中使用&environment。Doc : &environment后面跟一个绑定到 表示宏所在的词汇环境的环境 这个电话需要解释。此环境应与 宏函数,获取setf扩展,编译器宏函数,以及 macroexpand(例如)在计算宏的展开时 确保在 考虑了编译环境 解释 定义宏(本地或全局)的运算符必须定义代码在求值或编译之
&environment
。Doc
:
&environment
后面跟一个绑定到
表示宏所在的词汇环境的环境
这个电话需要解释。此环境应与
宏函数
,获取setf扩展
,编译器宏函数
,以及
macroexpand
(例如)在计算宏的展开时
确保在
考虑了编译环境
解释
定义宏(本地或全局)的运算符必须定义代码在求值或编译之前的扩展方式,因此可能需要扩展现有宏,这些宏的扩展可能取决于环境-因此宏定义需要环境
不是一个特殊的变量
特殊变量更危险,因为用户可能会重新绑定它们,并且在多线程代码中更难正确处理它们
例子
全世界:
发件人:
例如,当Lisp想要对表单进行宏扩展时,它需要知道哪个名称引用了哪个宏定义。这取决于全局可用的宏、通过
macrolet
本地绑定的宏或编译期间可用的宏。因此,环境对象可以针对不同的环境对表单进行宏扩展。环境变量向宏作者提供有关声明等的信息。在调用宏时强制执行。然后宏作者可以使用该信息自定义他选择如何展开宏。例如,他可以根据在环境中找到的声明添加或删除调试代码。例如,他可能会推断出要使用的表达式类型,并添加或减去代码以获得更好的性能
您可以编写许多常见的Lisp代码,而不必使用&environment。有些情况下,当这些都是很好的后续问题时,就变得有必要了。雷纳暗示了答案。这是一个有用的描述,谢谢,@Rainer。不过,也许可以通过一些示例代码进一步改进它?我还不清楚这将如何使用。(@sds,也许你的回答也会有同样的好处。)
(defmacro psetf (&whole whole-form
&rest args &environment env)
(labels ((recurse (args)
(multiple-value-bind (temps subforms stores setterform getterform)
(get-setf-expansion (car args) env)
(declare (ignore getterform))
(when (atom (cdr args))
(error-of-type 'source-program-error
:form whole-form
:detail whole-form
(TEXT "~S called with an odd number of arguments: ~S")
'psetf whole-form))
(wrap-let* (mapcar #'list temps subforms)
`(MULTIPLE-VALUE-BIND ,stores ,(second args)
,@(when (cddr args) (list (recurse (cddr args))))
,@(devalue-form setterform))))))
(when args `(,@(recurse args) NIL))))
(defmacro defconstant (name value &optional documentation
&environment env)
(destructuring-bind (name &key (test ''eql))
(alexandria:ensure-list name)
(macroexpand-1
`(alexandria:define-constant ,name ,value
:test ,test
,@(when documentation `(:documentation ,documentation)))
env)))