SICP 全笔记

Exercise 3.11. In section 3.2.3 we saw how the environment model described the behavior of procedures with local state. Now we have seen how internal definitions work. A typical message-passing procedure contains both of these aspects. Consider the bank account procedure of section 3.1.1:

(define (make-account balance)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (dispatch m)
    (cond ((eq? m 'withdraw) withdraw)
          ((eq? m 'deposit) deposit)
          (else (error "Unknown request -- MAKE-ACCOUNT"
                       m))))
  dispatch)

Show the environment structure generated by the sequence of interactions

(define acc (make-account 50))

((acc 'deposit) 40)
90

((acc 'withdraw) 60)
30

Where is the local state for acc kept? Suppose we define another account

(define acc2 (make-account 100))

How are the local states for the two accounts kept distinct? Which parts of the environment structure are shared between acc and acc2?

首先是定义 make-account:

+-------------------------------+
| make-account: ---+            |
|                  |            |
+------------------+------------+
                   |
                   |
                   |
                   |
                   |
                   v
   Parameter: balance
        body: (define (withdraw..))
              (define (deposit..))
              (define (dispatch..))
              dispatch

然后是定义 acc,

+-------------------------------------------------------------+
| make-account: ...                                           |
| acc ----+                                                   |
+---------+---------------------------------------------------+
          |                           ^
          |                           |
          |             E1            |
          |                +----------+---------+
          |                | withdraw:...       |
          |  +------------>| deposit:...        |
          |  |             | dispatch:...       |
          v  |             | balance: 50        |
  Parameter: m             +--------------------+
      body: ...

运行 ((acc ‘deposit) 40)

+-------------------------------------------------------------+
| make-account: ...                                           |
| acc ----+                                                   |
+---------+---------------------------------------------------+
          |                           ^
          |                           |
          |             E1            |
          |                +----------+---------+
          |                | withdraw:...       |     (set! balance (+ balance amount))
          |  +------------>| deposit:...        | <-----------------+
          |  |             | dispatch:...       |                   |
          v  |             | balance: 50 (-->90)|                   |
  Parameter: m             +--------------------+                   |
      body: ...                            ^             E3         |
                               E2          |                +-------+-----+
                                    +------+-------+        | amount: 40  |
                                    | m: 'deposit  |        +-------------+
                                    +--------------+
                                     (acc 'deposit)

得到结果 balance 将从 50 变为 90。

下一步是 ((acc 'withdraw) 60),它将首先绑定 dispatch 的 m,然后绑定 withdraw 的 amount 到 60,最后改变 balance

+-------------------------------------------------------------+
| make-account: ...                                           |
| acc ----+                                                   |
+---------+---------------------------------------------------+
          |                           ^
          |                           |
          |             E1            |
          |                +----------+---------+
          |                | withdraw:...       |       (begin (set! balance...))
          |  +------------>| deposit:...        |<---------------+
          |  |             | dispatch:...       |                |
          v  |             | balance: 90(-->30) |                |
  Parameter: m             +--------------------+                |
      body: ...                            ^                     |
                                E4         |                     |
                                    +------+------+   E5  +------+---------+
                                    | m:'with-draw|       | amount: 60     |
                                    +-------------+       +----------------+

可以看出 acc 的局部状态保存在 E1 中。当我们另外定义一个 (define acc2 (make-account 100)) 的时候,acc2 的环境将会创建一个 E6,这个 E6 将与 E1 的初始状态一样。 acc 与 acc2 共享的部分只会是代码,两者的环境是各自独立的。