<< Previous exercise (4.10) | Index | Next exercise (4.12) >>
meteorgans answer does not work. You must change at least define-variable! and set-variable-value! for the system to work.
; ; ; ; ;SKIP(no change): ; enclosing-environment ; first-frame ; the-empty-environment (define (make-frame variables values) (cons 'table (map cons variables values))) (define (frame-pairs frame) (cdr frame)) (define (add-binding-to-frame! var val frame) (set-cdr! frame (cons (cons var val) (frame-pairs frame)))) ;SKIP: ; extend-environment (define (lookup-variable-value var env) (define (env-loop env) (if (eq? env the-empty-environment) (error "Unbound variable" var) (let ((ret (assoc var (frame-pairs (first-frame env))))) (if ret (cdr ret) (env-loop (enclosing-environment env)))))) (env-loop env)) (define (set-variable-value! var val env) (define (env-loop env) (if (eq? env the-empty-environment) (error "Unbound variables -- SET!" var) (let ((ret (assoc var (frame-pairs (first-frame env))))) (if ret (set-cdr! ret val) (env-loop (enclosing-environment env)))))) (env-loop env)) (define (define-variable! var val env) (let* ((frame (first-frame env)) (ret (assoc var (frame-pairs frame)))) (if ret (set-cdr! ret val) (add-binding-to-frame! var val frame))))
Yep -- ultimately, I went with this approach too of using an "associative list". Although interestingly, attempting to use the Scheme implementation of assoc did not work and had to use the book's approach!
A way not use associative list:
(define (make-frame var val) (cons 'frame (map cons var val))) (define (add-binding-to-frame! var val frame) (set-cdr! frame (cons (cons var val) (cdr frame)))) (define (set-var-to-frame! var val frame) (let ((find #f)) (set-cdr! frame (map (lambda (pair) (if (eq? (car pair) var) (begin (set! find #t) (cons var val)) pair)) (cdr frame))) find)) (define (set-variable-value! var val env) (define (env-loop env) (if (eq? env the-empty-environment) (error "Unbound variable -- SET!" var) (if (set-var-to-frame! (first-frame frame)) 'done (env-loop (enclosing-environment env))))) (env-loop env)) (define (define-variable! var val env) (let ((frame (first-frame env))) (if (set-var-to-frame! var val frame) 'done (add-binding-to-frame! var val frame))))
meteorgan