SICP Exercise 3.4

Question

Modify the make-account procedure of Exercise 3.3 by adding another local state variable so that, if an account is accessed more than seven consecutive times with an incorrect password, it invokes the procedure call-the-cops.

Answer

(define (make-account balance password)
  (define counter 0)
  (define (call-the-cops)
    (display "You're going to jail..."))
  (define (pw-correct? pw)
    (if (eq? pw password)
        #t
        (begin (count-up) #f)))
  (define (count-up)
    (set! counter (+ counter 1)))
  (define (reset-counter)
    (set! counter 0))
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance
                     (- balance amount))
               balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (dispatch pw m)
    (if (< counter 7)
        (cond ((pw-correct? pw)
               (cond ((eq? m 'withdraw) withdraw)
                     ((eq? m 'deposit) deposit)
                     (else (error "Unknown request:
                 MAKE-ACCOUNT" m))))
              (else (λ (x) display "Incorrect password")))
        (λ (x) (call-the-cops))))
  dispatch)

Let’s test it:

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

((acc 'secret-password 'withdraw) 40)
((acc 'secret-password 'deposit) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)
((acc 'wrong-pw 'withdraw) 50)

Does what it’s supposed to:

60
110
"Incorrect password"
"Incorrect password"
"Incorrect password"
"Incorrect password"
"Incorrect password"
"Incorrect password"
"Incorrect password"
You're going to jail...