2015/12/21
SICP 問題 4.12
;; scanとenv-loopを抜き出す.
;; 見つかった時の手続きをprocで渡す.
(define (scan var vars vals proc)
(cond ((null? vars) #f)
((eq? var (car vars)) (proc var vars vals))
(else (scan var (cdr vars) (cdr vals) proc))))
(define (env-loop var env proc)
(if (eq? env the-empty-environment)
#f
(let ((frame (first-frame env)))
(let ((val (scan var
(frame-variables frame)
(frame-values frame)
proc)))
(or val (env-loop var (enclosing-environment env) proc))))))
(define (lookup-variable-value var env)
(let ((target (env-loop var env (lambda (var vars vals) vals))))
(if target
(car target)
(error "Unbound variable" var))))
(define (set-variable-value! var val env)
(let ((target (env-loop var env (lambda (var vars vals)
(set-car! vals val)))))
(if target
target
(error "Unbound variable: SET!" var))))
;; 見つかればtargetにvalsが束縛される.
(define (define-variable! var val env)
(let ((frame (first-frame env)))
(let ((target (scan var (frame-variables frame) (frame-values frame)
(lambda (var vars vals) vals))))
(if target
(set-car! target val)
(add-binding-to-frame! var val frame)))))