問題3-1〜4
第三章に入りました。最初は代入に関する練習問題です。
問題3-1のアキュムレータ手続きです。
(define (make-accumulator init) (let ((sum init)) (lambda (x) (begin (set! sum (+ sum x)) sum)))) (define A (make-accumulator 5)) (A 10) ;=>15 (A 10) ;=>25
問題3-2は、予め登録しておいた手続きが利用された回数を呼び出せるmake-monitoredを定義します。
(define (make-monitored proc) (let ((count 0)) (lambda (x) (if (eq? x 'how-many-calls?) count (begin (set! count (+ 1 count)) (proc x)))))) (define s (make-monitored sqrt)) (s 100) ;=>10 (s 'how-many-calls?) ;=>1 (s 'how-many-calls?) ;=>1 (s 64) ;=>8 (s 'how-many-calls?) ;=>2
問題3-3では、パスワードで保護されたmake-accountを作成します。
(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 (show-error-message amount) "Incorrect password") (define (dispatch pw m) (if (eq? pw password) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unkown request" m))) show-error-message)) dispatch) (define acc (make-account 100 'takuya)) ((acc 'takuya 'withdraw) 50) ;=>50 ((acc 'takuya 'withdraw) 60) ;=>"Insufficient funds" ((acc 'takuya 'deposit) 40) ;=>90 ((acc 'takuya 'withdraw) 60) ;=>30 ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password"
さらに問題3-4は、7回以上パスワードを間違えたら警察に通報するような機能を追加します。
(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 show-error-message (let ((err-count 1)) (lambda (acount) (if (< 7 err-count) call-the-police (begin (set! err-count (+ 1 err-count)) "Incorrect password"))))) (define call-the-police "we are calling the police") (define (dispatch pw m) (if (eq? pw password) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unkown request" m))) show-error-message)) dispatch) (define acc (make-account 100 'takuya)) ((acc 'takuya 'withdraw) 60) ;=>40 ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"Incorrect password" ((acc 'itoh 'withdraw) 20) ;=>"we are calling the police" ((acc 'itoh 'withdraw) 20) ;=>"we are calling the police"