我正在通过SICP工作。我在Section 3.1.1并且看着当地的州。我正在GNU Guile v2.0.11中评估这些练习。
我确实找到了similar question about this section,但似乎没有解决我正在努力解决的问题,或者我过于迟钝。
我正在研究的两个例子是:
(define new-withdraw
(let ((balance 100))
(lambda (amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))))
(define (make-withdraw balance)
(lambda (amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds")))
当我将第一个赋值给变量时:
(define a new-withdraw)
(define b new-withdraw)
我得到两个指向同一个过程对象的指针,状态在它们之间共享:
scheme@(guile-user)> a
$1 = #<procedure 1165880 at /path/to/file (amount)>
scheme@(guile-user)> b
$2 = #<procedure 1165880 at /path/to/file (amount)>
scheme@(guile-user)> (a 50)
$3 = 50
scheme@(guile-user)> (b 10)
$4 = 40
但是,当我实现第二个过程时,我会获得指向具有不同状态的两个不同过程对象的指针:
scheme@(guile-user)> (define c (make-withdraw 100))
scheme@(guile-user)> (define d (make-withdraw 100))
scheme@(guile-user)> c
$5 = #<procedure 14fdac0 at /path/to/file (amount)>
scheme@(guile-user)> d
$6 = #<procedure 1508360 at /path/to/file (amount)>
scheme@(guile-user)> (c 50)
$7 = 50
scheme@(guile-user)> (d 10)
$8 = 90
我已经阅读了这一部分并且没有明确的解释,我在搜索这一部分时遇到了麻烦。我理解一般来说状态方面发生了什么,但是我不明白这些程序之间的区别是允许一个人拥有一个通用状态,另一个是维持本地状态。
为什么第一个定义'new-withdraw'无法在多个任务中保持本地状态?似乎每次我们做出不同的任务时,lambda应该将余额的分配捕获到100(定义new-withdraw)。
答案 0 :(得分:3)
原因是在第二个例子中你每次都返回一个新的闭包,而在第一个例子中只有一个闭包,所以只有一个闭包。
如果您想要在第一种情况下采用与第二种情况相同的行为,请更改为:
(define (new-withdraw) ; this is a procedure now
(let ((balance 100))
(lambda (amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))))
(define a (new-withdraw)) ; called as a procedure
(define b (new-withdraw))
然后
> (a 50)
50
> (b 10)
90