我对常见的lisp中的& environment参数感到困惑。特别是,它有什么用处,为什么它是一个参数,而不是一个特殊的变量?
编辑:看一下如何在代码中使用&environment
的具体示例也很高兴。
答案 0 :(得分:4)
&environment
后跟一个绑定到的变量 环境代表宏观的词汇环境 呼叫是要解释的。应该使用此环境macro-function
,get-setf-expansion
,compiler-macro-function
和 {(1}}(例如)在计算宏的扩展时,到 确保在中建立任何词汇绑定或定义 编译环境被考虑在内。
定义宏(本地或全局)的运算符必须在评估或编译之前定义代码的扩展方式,因此可能需要扩展现有的宏,其扩展可能取决于环境 - 因此宏定义需要环境。
特殊变量更危险,因为用户可能会重新绑定它们,因为它们在多线程代码中更难以正确处理。
遍布places.lisp
:
macroexpand
来自iolib/src/new-cl/definitions.lisp
:
(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))))
答案 1 :(得分:3)
例如,当Lisp想要 macroexpand 表单时,需要知道哪个名称引用了什么宏定义。这可能取决于全局可用的宏,通过macrolet
的本地绑定宏或编译期间可用的宏。因此,环境对象可以针对不同的环境宏扩展表单。
答案 2 :(得分:1)
环境变量向宏作者提供有关声明等的信息。人。在调用宏时强制执行。然后,宏作者可以使用该信息来自定义他选择如何扩展宏。例如,他可以根据他在环境中找到的声明来添加或减去调试代码。例如,他可能会推断出他使用的表达式类型,并添加或减少代码以获得更好的性能。
您可以编写很多Common Lisp代码,而不会使用&环境。在某些情况下,有必要,当这些问题可以提出良好的后续问题时。雷纳暗示了对此的回答。