gpt4 book ai didi

variables - 在创建 lambda 时捕获变量的值

转载 作者:太空宇宙 更新时间:2023-11-03 18:37:19 24 4
gpt4 key购买 nike

如果我们给一个变量赋值:

(setf i 10)

然后创建一个关闭它的 lambda 函数:

(setf f #'(lambda () i))

我们有行为

(incf i)    ;=> 11
(funcall f) ;=> 11

相反,我希望函数在创建函数时始终返回 i 的值。例如:

(incf i)    ;=> 11
(funcall f) ;=> 10

本质上,我想将 i 变成 lambda 体内的文字。这在 Common Lisp 中可以做到吗?原因是我在一个循环中创建了多个 lambda,并且需要在它们的主体中使用索引,而它们在创建后不会发生变化。

最佳答案

只需将变量与值的副本绑定(bind)即可。例如:

(let ((i i))
(lambda () i))

这实际上是一个迭代构造的重要技术,因为像

(loop for i from 1 to 10
collecting (lambda () i))

可能会对相同的变量返回十个闭包,因此有必要这样写:

(loop for i from 1 to 10
collecting (let ((i i)) (lambda () i)))

如果你真的只需要一个返回值的函数,你也可以使用 constantly (但我预计实际用例会更复杂):

(loop for i from 1 to 10
collecting (constantly i))

在某些情况下,迭代形式的歧义实际上是由标准指定的。例如,对于 dotimes , dolist

It is implementation-dependent whether dotimes establishes a new binding of var on each iteration or whether it establishes a binding for var once at the beginning and then assigns it on any subsequent iterations.

更原始的do , 然而,实际上指定了表单的一组绑定(bind),并且它们在每次迭代时更新(添加了强调):

At the beginning of each iteration other than the first, vars are updated as follows. …

这种模糊性为实现提供了更多的灵 active 。 Dolist,例如可以使用以下任一定义:

(defmacro dolist ((var list &optional result) &body body)
`(progn (mapcar #'(lambda (,var)
,@(ex:body-declarations body)
(tagbody
,@(ex:body-tags-and-statements body)))
,list)
(let ((,var nil))
,result)))

(defmacro dolist ((var list &optional result) &body body)
(let ((l (gensym (string '#:list-))))
`(do* ((,l ,list (rest ,l))
(,var (first ,l) (first ,l)))
((endp ,l) ,result)
,@body)))

关于variables - 在创建 lambda 时捕获变量的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26706107/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com