さかもとのブログ

つらつらと

SICP演習問題4.11

map, assoc, cut を使ってしまった.完全に反則だな.
時間があれば書き直す.

でもassocは演習問題4.5の中で,もともと使っているぞ?
と自分を慰める.

しかもテストをしていないので,たぶん間違えがある.

;;exercise4.11
(define (make-frame variables values)
  (map cons variables values))

(define (frame-variables frame)
  (map car frame))

(define (frame-values frame)
  (map cdr frame))

(define (add-binding-to-frame! variable value frame)
  (set-car! frame (cons (cons variable value) frame)))

(define (lookup-variable-value variable env)
  (define (env-loop env)
    (define (scan variables values)
      (cond [(null? variables)
             (env-loop (enclosing-environment env))]
            [(assoc variable variables)
             (set-cdr! (assoc variable variables)]
            [else (scan (cdr variables) (cdr values))]))
    (if (eq? env the-empty-environment)
        (error "Unbound variable" variable)
        (let ((frame (first-frame env)))
          (scan (frame-variables frame)
                (frame-values frame)))))
  (env-loop env))

(define (set-variable-value! variable value env)
  (define (env-loop env)
    (define (scan variable values)
      (cond [(null? variables)
             (env-loop (enclosing-environment env))]
            [(assoc variable variables) => (cut set-cdr! <> value)]
            [else (scan (cdr variables) (cdr values))]))
    (if (eq? env the-empty-environment)
        (error "Unbound variables -- SET!" variable)
        (let ((frame (first-frame env)))
          (scan (frame-variables frame)
                (frame-values frame)))))
  (env-loop env))

(define (define-variable! variable value env)
  (let ((frame (first-frame env)))
    (define (scan variables values)
      (cond [(null? variables)
             (add-binding-to-frame variable value frame)]
            [(assoc variable variables) => (cut set-cdr! <> value)]
            [else (scan (cdr variables) (cdr values))]))
    (scan (frame-variables frame)
          (frame-values frame))))