SICP問題4.12
set-variable-value!, define-variable!およびlookup-variable-valueから共通パターンを取り込んだ抽象の定義。
define-variable!と次の問題まで含めて考えて、手続きを渡せるようにしておく。
(define (scan var vars vals proc) (cond ((null? vars) #f) ((eq? var (car vars)) (proc vars vals)) (else (scan var (cdr vars) (cdr vals) proc)))) (define (scan-env-loop var env proc) (if (eq? env the-empty-environment) #f (let ((frame (first-frame env))) (let ((bind-pair (scan var (frame-variables frame) (frame-values frame) proc))) (if (not bind-pair) (scan-env-loop var (enclosing-environment env) proc) bind-pair)))))
上の抽象を使って再定義した手続き
(define (lookup-variable-value var env) (let ((val (scan-env-loop var env (lambda (vars vals) (car vals))))) (if (not val) (error "Unbound variable" var) val))) (define (set-variable-value! var val env) (let ((val (scan-env-loop var env (lambda (vars vals) (set-car! vals val) #t)))) (if (not val) (error "Unbound variable -- SET!" var) val))) (define (define-variable! var val env) (let ((frame (first-frame env))) (let ((result (scan var (frame-variables frame) (frame-values frame) (lambda (vars vals) (set-car! vals val) #t)))) (if (not result) (add-binding-to-frame! var val frame)))))