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)))))

© 2022 wat-aro