SICP第3.1.1节 - 程序中的本地状态似乎不一致

时间:2014-12-21 16:35:41

标签: scheme closures state sicp

我正在通过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)。

1 个答案:

答案 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