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))))