SICP Section 3.1.1 - Local state in procedures seems inconsistent

╄→гoц情女王★ 提交于 2019-12-14 02:18:54

问题


I am working my way through SICP. I am on Section 3.1.1 and looking at local state. I am evaluating these exercises in GNU Guile v2.0.11.

I did find a similar question about this section, but it seems not to address the point I am struggling with, or I am overly obtuse.

The two examples I am looking at are these:

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

When I assign the first to a variable with:

(define a new-withdraw)
(define b new-withdraw)

I get two pointers to the same procedure object and the state is shared between them:

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

When I implement the second procedure, though, I get pointers to two distinct procedure objects with distinct state:

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

I've read through the section and there is no clear explanation of this, and I'm having trouble finding anything when I search for this section. I understand what is happening in terms of state in general, but I don't get what the difference between these procedures is that allows one to have a single universal state, and the other to maintain local state.

Why is the first definition, 'new-withdraw', unable to maintain local state across multiple assignments? It seems that the lambda should be capturing the assignment of balance to 100 every time we make a different assignment (define new-withdraw).


回答1:


The reason is that in the second example you return a fresh closure every time, whereas in the first example there is only one closure, so only one state.

If you want the same behaviour in the first case as you have in the second case, change to:

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

then

> (a 50)
50
> (b 10)
90


来源:https://stackoverflow.com/questions/27591403/sicp-section-3-1-1-local-state-in-procedures-seems-inconsistent

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!