Exercise 3.10. In the make-withdraw procedure, the local variable balance is created as a parameter of make-withdraw. We could also create the local state variable explicitly, using let, as follows:
(define (make-withdraw initial-amount)
(let ((balance initial-amount))
(lambda (amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))))
Recall from section 1.3.2 that let is simply syntactic sugar for a procedure call:
(let ((<var> <exp>)) <body>)
is interpreted as an alternate syntax for
((lambda (<var>) <body>) <exp>)
Use the environment model to analyze this alternate version of make-withdraw, drawing figures like the ones above to illustrate the interactions
(define W1 (make-withdraw 100))
(W1 50)
(define W2 (make-withdraw 100))
Show that the two versions of make-withdraw create objects with the same behavior. How do the environment structures differ for the two versions?
首先是 make-withdraw
+------------------------------+
| make-withdraw: ----+ |
| | |
+--------------------+---------+
|
|
|
|
|
Parameter: initial-amount
body: (let ((balance initial-amount))
(lambda (amount)...))
在调用 (define W1 (make-withdraw 100)) 时的环境图
+-------------------------------------------------+
| make-withdraw: ... |
| W1 ----+ |
+--------+----------------------------------------+
| ^
| |
| E1 |
| +---------+----------+
| +------> |initial-amount:100 |
| | |balance: 100 |
v | +--------------------+
Parameter: amount
body: ...
调用 (W1 50) 时
+-------------------------------------------------+
| make-withdraw: ... |
| W1 ----+ |
+--------+----------------------------------------+
| ^
| |
| E1 |
| +---------+----------+
| +------> |initial-amount:100 |
| | |balance: 100 | <------------+
v | +--------------------+ |
Parameter: amount | E2
body: ... +-------+-------+
| amount: 50 |
| |
+---------------+
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds")
在 E2 环境中运行代码时,balance 在 E2 中找不到,所以到 E2 的上一个 frame 中找,得到结构是 balance 为 100,于是运行 set! 得到结果
+-------------------------------------------------+
| make-withdraw: ... |
| W1 ----+ |
+--------+----------------------------------------+
| ^
| |
| E2 |
| +---------+----------+
| +------> |initial-amount:100 |
| | |balance: 50 |
v | +--------------------+
Parameter: amount
body: ...
运行 (define W2 (make-withdraw 100)) 时,会构造一个新的环境 E3,与之前的 E1,E2 都没有关系。
+-------------------------------------------------+
| make-withdraw: ... |
| W1: ... |
| W2:----+ |
+--------+----------------------------------------+
| ^
| |
| E3 |
| +---------+----------+
| +------> |initial-amount:100 |
| | |balance: 100 |
v | +--------------------+
Parameter: amount
body: ...