为什么这些表单会有这样的行为?
CL-USER>
(setf *closures*
(loop for num in (list 1 2 3 4)
collect (lambda ()
num)))
(
#<COMPILED-LEXICAL-CLOSURE #x302004932E1F>
#<COMPILED-LEXICAL-CLOSURE #x302004932DCF>
#<COMPILED-LEXICAL-CLOSURE #x302004932D7F>
#<COMPILED-LEXICAL-CLOSURE #x302004932D2F>)
CL-USER>
(funcall (first *closures*))
4
CL-USER>
(funcall (second *closures*))
4我期望第一个funcall返回1,第二个返回2,依此类推。这种行为与Clozure Common Lisp和Steel-Bank Common Lisp实现都是一致的。
如果我使用dolist将循环宏重做为一个版本,我期望的是返回的结果:
(setf *closures*
(let ((out))
(dolist (item (list 1 2 3 4) (reverse out))
(push (lambda () item) out))))
(
#<COMPILED-LEXICAL-CLOSURE #x302004A12C4F>
#<COMPILED-LEXICAL-CLOSURE #x302004A12BFF>
#<COMPILED-LEXICAL-CLOSURE #x302004A12BAF>
#<COMPILED-LEXICAL-CLOSURE #x302004A12B5F>)
CL-USER>
(funcall (first *closures*))
1
CL-USER>
(funcall (second *closures*))
2CL-用户>
循环宏版本是怎么回事?
发布于 2013-03-30 12:20:29
num是所有lambda共享的相同变量。
使用
(setf *closures*
(loop for num in (list 1 2 3 4)
collect (let ((num1 num))
(lambda ()
num1))))num1是每次迭代的新变量。
对于dolist,“dolist是在每次迭代中建立新的var绑定,还是在开始时为var建立一次绑定,然后在任何后续迭代中分配它,这取决于实现。”(CLHS,Macro DOLIST)因此,它可能在一个实现上工作,而在另一个实现上失败。
发布于 2013-03-30 18:12:11
在计算循环的过程中,名称num表示相同的绑定。也许你想这样写:
(mapcar 'constantly (list 1 2 3 4))才能明白你的意思。
https://stackoverflow.com/questions/15714537
复制相似问题