Exercise 3.7. Consider the bank account objects created by make-account, with the password modification described in exercise 3.3. Suppose that our banking system requires the ability to make joint accounts. Define a procedure make-joint that accomplishes this. Make-joint should take three arguments. The first is a password-protected account. The second argument must match the password with which the account was defined in order for the make-joint operation to proceed. The third argument is a new password. Make-joint is to create an additional access to the original account using the new password. For example, if peter-acc is a bank account with password open-sesame, then
(define paul-acc
(make-joint peter-acc 'open-sesame 'rosebud))
will allow one to make transactions on peter-acc using the name paul-acc and the password rosebud. You may wish to modify your solution to exercise 3.3 to accommodate this new feature.
本题要在 练习 3-3 的基础上,增加一个可以外部访问 balance 的途径,访问的操作和 dispatch 一模一样。
我们发现其实新添加的关联账户的操作实际就是返回另外一个 dispatch,这样在 dispatch 中就可以访问内部的 balance 的值了。这里不能使用 (make-account balance new-password) 重新新建一个账户,那样的话只是暂时的两个账户的 balance 的值相等而已。
最简单地我们可以使用下面这样的方法来,只需要修改 dispatch 的密码对比的地方即可。
(define (joint new-password)
(define (dispatch pwd m)
(cond ((not (eq? pwd new-password)) password-error)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
((eq? m 'joint) joint)
((eq? m 'print-balance) print-balance)
(else (error "Unknown request -- MAKE-ACCOUNT"
m))))
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 (joint new-password)
(receiver new-password))
(define (dispatch m)
(cond ((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
((eq? m 'joint) joint)
((eq? m 'print-balance) print-balance)
(else (error "Unknown request -- MAKE-ACCOUNT"
m))))
(define (receiver pwd)
(lambda (input-pwd m)
(cond ((not (eq? input-pwd pwd)) password-error)
(else
(dispatch m)))))
(receiver password))
(define (make-joint account its-password new-password)
((account its-password 'joint) new-password))