<< Previous exercise (4.5) | Index | Next exercise (4.7) >>


 ;; in eval, add this: 
  ((let? expr) (evaln (let->combination expr) env)) 
 ;; let expression 
 (define (let? expr) (tagged-list? expr 'let)) 
 (define (let-vars expr) (map car (cadr expr))) 
 (define (let-inits expr) (map cadr (cadr expr))) 
 (define (let-body expr) (cddr expr)) 
 (define (let->combination expr) 
   (list (make-lambda (let-vars expr) (let-body expr)) 
         (let-inits expr))) 

Because the initial values for the vars serve as the remainder of the list (cdr) instead of a separate list, the let->combination should be defined using 'cons' instead of 'list'.

 (define (let->combination expr) 
   (cons (make-lambda (let-vars expr) (let-body expr)) 
         (let-inits expr))) 

I think let-body above seems to have a bug.

 (define (let-body expr) (caddr expr)) 

because body part is one of three parts of let expression list.

Body part may contain several expressions, so 'cddr' is used to point all the rest parts.


 ;; without using map 
 (define (let-bindings exp) 
   (cadr exp)) 
 (define (let-body exp) 
   (cddr exp)) 
 (define (bindings->params bindings) 
   (if (null? bindings) 
        (caar bindings) 
        (bindings->params (cdr bindings))))) 
 (define (bindings->args bindings) 
   (if (null? bindings) 
        (cadar bindings) 
        (bindings->args (cdr bindings))))) 
 ;; TODO Check if bindings are pairs 
 (define (let->combination exp) 
     (bindings->params (let-bindings exp)) 
     (let-body exp)) 
    (bindings->args (let-bindings exp))))