Lisp 为什么此defun闭包的行为与defparameter闭包不同?

Lisp 为什么此defun闭包的行为与defparameter闭包不同?,lisp,closures,common-lisp,Lisp,Closures,Common Lisp,考虑以下两个方面: (defparameter *lfn* (let ((count 0)) #'(lambda () (incf count)))) (defun testclosure () (let ((count 0)) #'(lambda () (incf count)))) 为什么他们的行为有所不同: CL-USER> (funcall (testclosure)) 1 CL-USER> (funcall (test

考虑以下两个方面:

(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
版本中不关闭。这是为什么呢?

当您创建
*lfn*
时,您正在一个闭包中创建函数。。调用它将增加关闭的over计数,并对其求值

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

答案是,计数在这两种情况下都是闭合的,但在您的示例中,您创建了一个新的闭包,并且只使用了一次或几次。

对此进行了很好的解释,但如果一个具有更明确副作用的示例更清楚地说明了这一点,请考虑:

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
,而不是重新评估生成其原始值的表单。相比之下,请考虑调用一个函数,该函数的主体为(PRON(Prime'Hello)0)`:< /P>
每次调用
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
每次调用时都返回一个新的闭包

(defun testclosure ()
    (let ((count 0))
      #'(lambda ()
      (incf count))))