Common lisp 何谓&;公共Lisp中的环境?

Common lisp 何谓&;公共Lisp中的环境?,common-lisp,environment,Common Lisp,Environment,我对common lisp中的&environment参数感到困惑。特别是,它的用途是什么?为什么它是一个参数,而不是一个特殊变量 编辑:如果能看到一个具体的例子,说明如何在代码中使用&environment。Doc : &environment后面跟一个绑定到 表示宏所在的词汇环境的环境 这个电话需要解释。此环境应与 宏函数,获取setf扩展,编译器宏函数,以及 macroexpand(例如)在计算宏的展开时 确保在 考虑了编译环境 解释 定义宏(本地或全局)的运算符必须定义代码在求值或编译之

我对common lisp中的&environment参数感到困惑。特别是,它的用途是什么?为什么它是一个参数,而不是一个特殊变量

编辑:如果能看到一个具体的例子,说明如何在代码中使用
&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)))