最近自学 MIT 6.5151 课程时,我按照 ps0 的要求阅读了 SICP 1 到 2.1(也按照 CS 61A Notes 的要求阅读了 2.2.1),然后阅读了 Software Design for Flexibility (SDF) Prologue, Chapter 1以及部分方案附录。
我在阅读《方案附录》时遇到了这个问题:
例如,我们可以使用set!制作一个每次调用时都会增加计数的设备:
(define (make-counter) (let ((count 0)) (lambda () (set! count (+ count 1)) count)))
让我们制作两个计数器:
(define c1 (make-counter)) (define c2 (make-counter))
这两个计数器具有独立的本地状态。
这是一个与 this 类似的问题,但使用
(count)
而不是 count
:
(define (count)
(let ((cont 0))
(lambda ()
(set! cont (+ cont 1))
cont)))
然后在 MIT-Scheme 中执行以下操作:
1 ]=> ((count))
;Value: 1
1 ]=> ((count))
;Value: 1
有人可以告诉我这个版本和原来的
define count
版本有什么区别吗?是否由于上述原因,每次调用 lambda
都会创建一个 new实例
((make-counter))
,而原始实例则不会? (最好能参考一份迄今为止尚未阅读的 SICP 章节。)
您的
count
功能
(define (count)
(let ((cont 0))
(lambda ()
(set! cont (+ cont 1))
cont)))
与您还显示的
make-counter
函数相同,只是变量名称不同。 count
是一个返回函数的函数;调用它会增加一个计数器。每个返回的函数在其词法环境中都有自己唯一的 cont
变量副本。如果你这样做
(define c1 (count))
(define c2 (count))
然后
c1
和 c2
有自己独立的内部计数器变量。 ((count))
首先执行(count)
,返回一个新函数,然后执行它,返回它返回的内容。然后,这个新函数会在某个时刻被垃圾收集,因为没有任何引用它可以使其保持活动状态;只能叫一次。
链接问题中的定义是
(define count
(let ((cont 0))
(lambda ()
(set! cont (+ cont 1))
cont)))
将
count
定义为 返回的值
(let ((cont 0))
(lambda ()
(set! cont (+ cont 1))
cont))
这是一个函数。因此,每次调用此版本的
count
时,该函数都会递增其环境中的 cont
变量。相当于
(define count (make-counter))