23 hours ago
my attempt to do the exercises in sicp.
Monday, August 17, 2009
sicp exercise 3.7
;; 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.
;; The solution is to seperate the account balance management and password management.
(define (make-balance balance)
"This procedure is exclusively for balance management"
(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)
(define (make-account balance password)
"This procedure is exclusively for passwd management
and gaining access to balance management if the password is correct"
(define (get-balance)
(define balance-ref balance)
balance-ref)
(define (wrong-passwd arg)
"Incorrect password")
(define (check-pass pass)
(eq? pass password))
(define (set-passwd pass)
(set! password pass))
(define (dispatch passwd cmd)
(if (eq? cmd 'check-passwd)
(check-pass passwd)
(if (eq? passwd password)
(cond ((eq? cmd 'get-balance) (get-balance))
((eq? cmd 'change-passwd) set-passwd)
((eq? cmd 'check-passwd) #t)
(else (balance cmd)))
wrong-passwd)))
dispatch)
(define (make-joint-account accnt accnt-passwd passwd)
(if (accnt accnt-passwd 'check-passwd)
(make-account (accnt accnt-passwd 'get-balance) passwd)
"Wrong passwd..."))
(define peter-acc (make-account (make-balance 1000) 'open-sesame))
(display ((peter-acc 'open-sesame 'withdraw) 40)) (newline)
(display ((peter-acc 'open-sesame 'withdraw) 40)) (newline)
(display ((peter-acc 'open-sesame 'withdraw) 40)) (newline)
(display ((peter-acc 'some-other-password 'deposit) 50)) (newline)
(define paul-acc (make-joint-account peter-acc 'open-sesame 'rosebud))
(display ((paul-acc 'rosebud 'withdraw) 40)) (newline)
(display ((paul-acc 'rosebud 'withdraw) 40)) (newline)
(display ((paul-acc 'rosebud 'withdraw) 40)) (newline)
(display ((paul-acc 'some-other-password 'deposit) 50)) (newline)
;; paul can change his passwd, independent of peter
((paul-acc 'rosebud 'change-passwd) 'lotus-leaf)
(display ((paul-acc 'lotus-leaf 'withdraw) 40)) (newline)
;; peter is not affected by change in paul's password
(display ((peter-acc 'open-sesame 'withdraw) 40)) (newline)
Subscribe to:
Post Comments (Atom)
3 comments:
This seemed to work fine, while being shorter:
(define (make-joint account oldpass newpass)
(lambda (try method)
(if (eq? try newpass)
(account oldpass method)
(error "Incorrect password"))))
Any apparent problem with that approach?
As i have already mentioned in the solution that "The solution is to seperate the account balance management and password management."
Thats why my solution is so elaborate.
Thanks for your comment :)
ferd's solution is more elegant, since it doesn't require changes to pre-existing code.
Post a Comment