Упражнение 3.4.
Модифицируйте процедуру make-account из упражнения 3.3, добавив еще одну локальную пе-
ременную, так, чтобы, если происходит более семи попыток доступа подряд с неверным паролем,
вызывалась процедура call-the-cops (вызвать полицию).
Решение в лоб
(define max-tryes 7)
(define (call-the-cops arg1 . args) (error "За вами уже выехали"))
(define (make-account balance password)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount)) balance)
"Недостаточно денег на счете"))
(define (deposit amount) (set! balance (+ balance amount)) balance)
(let ((wrong-tryes 0))
(define (dispatch pass m)
(if (eq? pass password)
(begin
(set! wrong-tryes 0)
(cond ((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Неизвестный вызов -- MAKE-ACCOUNT" m))))
(begin (set! wrong-tryes (+ wrong-tryes 1))
(if (> wrong-tryes max-tryes) call-the-cops (λ(arg . other)"Неверный пароль")))))
dispatch))
Но, на самом деле, не для таких решений мы эту книгу читали. Задачи диспетчеризации и ограничения доступа совсем разные и никак не могут укладываться в одной функции написанной программистом в здравом уме.
Вынесем логику по проверке пароля в отдельную функцию
(define (password-checker-wrapper func password max-tryes)
(define (call-the-cops arg1 . args) (error "За вами уже выехали"))
(let ((wrong-tryes 0))
(λ (pass . args)
(cond ((eq? pass password) (begin (set! wrong-tryes 0)(apply func args)))
((= wrong-tryes max-tryes) call-the-cops)
(else (begin (set! wrong-tryes(+ wrong-tryes 1))
(λ(arg . other)"Неверный пароль")))))))
После этого мы можем вернуть make-accountпочти в первозданное состояние лишь завернув dispatch (который остается таким же как и до введение политики безопасности)
(define (make-account balance password)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount)) balance)
"Недостаточно денег на счете"))
(define (deposit amount) (set! balance (+ balance amount)) balance)
(define (dispatch m)
(cond ((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Неизвестный вызов -- MAKE-ACCOUNT" m))))
(password-checker-wrapper dispatch password 7))
Комментариев нет:
Отправить комментарий