练习 3.4

带报警功能的 make-account 定义如下(大部分代码重用自 练习 3.3 ):

;;; 4-make-account.scm

(define (make-account blance password)

    (let ((max-try-times 7)
          (try-times 0))

        (define (withdraw amount)
            (if (>= blance amount)
                (begin (set! blance (- blance amount))
                       blance)
                "Insufficient funds"))

        (define (deposit amount)
            (set! blance (+ blance amount)))

        (define (password-match? given-password)                         
                (eq? given-password password))                          

        (define (display-wrong-password-message useless-arg)                
            (display "Incorrect password"))                                

        (define (dispatch given-password mode)          
            (if (password-match? given-password)                          
                (begin
                    (set! try-times 0)                          ; 成功登录之后清零计数器
                    (cond ((eq? mode 'withdraw)
                            withdraw)
                          ((eq? mode 'deposit)
                            deposit)
                          (else
                            (error "Unknow request -- MAKE-ACCOUNT" mode))))
                (begin          
                    (set! try-times (+ 1 try-times))            ; 进行计数
                    (if (>= try-times max-try-times)
                        (call-the-cops)
                        display-wrong-password-message))))
    
        dispatch))

(define (call-the-cops)
    (error "You try too much times, calling the cops ..."))

测试:

1 ]=> (load "4-make-account.scm")

;Loading "4-make-account.scm"... done
;Value: call-the-cops

1 ]=> (define acc (make-account 100 'secret-password))

;Value: acc

1 ]=> ((acc 'wrong-password 'withdraw) 50)
Incorrect password
;Unspecified return value

1 ]=> ((acc 'wrong-password 'withdraw) 50)
Incorrect password
;Unspecified return value

1 ]=> ((acc 'wrong-password 'withdraw) 50)
Incorrect password
;Unspecified return value

1 ]=> ((acc 'wrong-password 'withdraw) 50)
Incorrect password
;Unspecified return value

1 ]=> ((acc 'wrong-password 'withdraw) 50)
Incorrect password
;Unspecified return value

1 ]=> ((acc 'wrong-password 'withdraw) 50)
Incorrect password
;Unspecified return value

1 ]=> ((acc 'wrong-password 'withdraw) 50)

;You try too much times, calling the cops ...
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.

讨论

blog comments powered by Disqus