SICP 全笔记

Exercise 3.3. Modify the make-account procedure so that it creates password-protected accounts. That is, make-account should take a symbol as an additional argument, as in

(define acc (make-account 100 'secret-password))

The resulting account object should process a request only if it is accompanied by the password with which the account was created, and should otherwise return a complaint:

((acc 'secret-password 'withdraw) 40)
60

((acc 'some-other-password 'deposit) 50)
"Incorrect password"

添加密码机制需要

  1. 另外定义一个过程 password-error
  2. 修改 make-accountdispatch 的接口
  3. dispatch 需要首先判断密码是否正确
(define (make-account balance password)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (password-error dummy) "Incorrect password")
  (define (dispatch pwd m)
    (cond ((not (eq? pwd password)) password-error)
          ((eq? m 'withdraw) withdraw)
          ((eq? m 'deposit) deposit)
          (else (error "Unknown request -- MAKE-ACCOUNT"
                       m))))
  dispatch)

;;; tests begin
(load "../testframe.scm")

(let ((acc (make-account 100 'pwd)))
  (assert= ((acc 'pwd 'deposit) 100) 200)
  (assert= ((acc 'pwd 'withdraw) 200) 0)
  (assertequal? ((acc 'pwd 'withdraw) 100) "Insufficient funds")
  (assertequal? ((acc 'pwd1 'deposit) 100) "Incorrect password")
  (assert= ((acc 'pwd 'deposit) 100) 100))

需要注意的是 password-error 过程需要一个参数占位,以便下面这样的调用不会出错:

((acc 'some-other-password 'deposit) 50)