考虑这两个:
(defparameter *lfn*
(let ((count 0))
#'(lambda ()
(incf count))))
(defun testclosure ()
(let ((count 0))
#'(lambda ()
(incf count))))
为什么他们不同的表现:
CL-USER> (funcall (testclosure))
1
CL-USER> (funcall (testclosure))
1
CL-USER> (funcall *lfn*)
1
CL-USER> (funcall *lfn*)
2
count
在关闭了defparameter
版本,但不是在defun
版本。 为什么是这样?
Sylwester的回答解释了这个非常好,但在的情况下,用更明确的副作用的例子使这再清楚不过,考虑:
CL-USER> (defparameter *foo* (progn (print 'hello) 0))
HELLO
*FOO*
CL-USER> *foo*
0
CL-USER> *foo*
0
在定义*foo*
,所述(progn (print 'hello) 0)
被评估一次,所以hello
被打印出来,并且所述值是0
,这成为的值*foo*
。 评价*foo*
后面只是意味着仰视*foo*
的值( 0
) , not reëvaluating the form that produced its original value. In contrast, consider calling a function whose body is
, not reëvaluating the form that produced its original value. In contrast, consider calling a function whose body is
(progn这个(打印“你好)0)`:
CL-USER> (defun foo () (progn (print 'hello) 0))
FOO
CL-USER> (foo)
HELLO
0
CL-USER> (foo)
HELLO
0
CL-USER> (foo)
HELLO
0
每次foo
被调用时, (progn (print 'hello) 0)
被评估,所以hello
被印刷和0
被返回。 看到这个例子之后,你的代码应该是更清楚一点。
(defparameter *lfn*
(let ((count 0))
#'(lambda ()
(incf count))))
(let ...)
计算一次,而该评估产生它的价值关闭*lfn*
。 在另一方面,在
(defun testclosure ()
(let ((count 0))
#'(lambda ()
(incf count))))
(let ...)
评估每一个时间testclosure
被调用时,一个新的闭包每次返回。
当你在进行*lfn*
您在一个闭包内创建一个函数调用..这无疑增加了关闭了计数和评价它。
testclosure
不一样的你做了什么*lfm*
为每它被调用的时间。 从而:
(defparameter *lfn2* (testclosure))
(funcall *lfn2*) ; ==> 1
(funcall *lfn2*) ; ==> 2
(funcall *lfn2*) ; ==> 3
将完全一样, *lfn*
,使得连续调用它会增加返回的值。 然而
(funcall (testclosure)) ; ==> 1 (and the closure can be recycled)
(funcall (testclosure)) ; ==> 1 (and the closure can be recycled)
在这里,你正在做funcall
在新创建的闭包,你不存储连续调用,所以它会返回1。然后你正在做funcall
上,你也不要存放一个完全新的封闭再次,它的第一个电话也计算结果为1。
因此,答案是,计数在两个关闭了,但在你比如你正在创建一个新的闭包,并用它只有一次,几次。
值*lfn*
是一个封闭。
该函数testclosure
返回每个调用它一个新的封闭。
文章来源: Why does this defun closure not behave the same as the defparameter closure?