为什么这个封闭defun函数的行为方式一样defparameter关闭?(Why does this

2019-10-18 23:54发布

考虑这两个:

(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版本。 为什么是这样?

Answer 1:

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被调用时,一个新的闭包每次返回。



Answer 2:

当你在进行*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。

因此,答案是,计数在两个关闭了,但在你比如你正在创建一个新的闭包,并用它只有一次,几次。



Answer 3:

*lfn*是一个封闭。

该函数testclosure返回每个调用它一个新的封闭。



文章来源: Why does this defun closure not behave the same as the defparameter closure?