sicp-ex-4.11



<< Previous exercise (4.10) | Index | Next exercise (4.12) >>


meteorgan

  
  
  
  
 (define (make-frame variables values) 
         (if (= (length variables) (length values)) 
                 (map cons variables values) 
                 (error "length mismatch -- MAKE-FRAME" variables values))) 
  
 (define (frame-variables frame) (map car frame)) 
 (define (frame-values frame) (map cdr frame)) 

Rptx

meteorgans answer does not work. You must change at least define-variable! and set-variable-value! for the system to work.


felix021 (a full version)

 ; 
 ; 
 ; 
 ; 
 ;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!



mazj

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