sicp-ex-4.5



<< Previous exercise (4.4) | Index | Next exercise (4.6) >>


Unknown

 (define (eval-cond exp env) 
   (let ((clauses (cdr exp)) 
         (predicate car) 
         (consequent cdr)) 
     (define (imply-clause? clause) (eq? (cadr clause)  '=>)) 
     (define (else-clause?  clause) (eq? (car clause) 'else)) 
     (define (rec-eval clauses) 
       (if (null? clauses) 'false; checked all, no else-clause 
           (let ((first-clause (car clauses))) 
             (cond ((else-clause? first-clause) (eval-sequence (consequent first-clause) env)) 
                   ((imply-clause? first-clause) (let ((evaluated (eval (predicate first-clause) env))) 
                                                   (if (true? evaluated) 
                                                       (apply (eval (caddr first-clause) env) 
                                                              (list evaluated)) 
                                                       'false))) 
                   (else (if (true? (eval (predicate first-clause) env)) 
                             (eval-sequence (consequent first-clause) env) 
                             'false)))))) 
     (rec-eval clauses))) 

aos

My approach just changes the way expand-clauses is handled. I don't do any of the evaluation and just create a separate if clause with its own expression.

 (define (expand-clauses clauses env) 
   (if (null? clauses) 
       'false ; no else clause 
       (let ((first (car clauses)) 
             (rest (cdr clauses))) 
         (if (cond-else-clause? first) 
             (if (null? rest) 
                 (sequence->exp 
                   (cond-actions first)) 
                 (error "ELSE clauses isn't 
                         last: COND->IF" 
                         clauses)) 
         (if (eq? (car (cond-actions first)) '=>) ; <---- here 
             (make-if (cond-predicate first) 
                      (list (cadr (cond-actions first)) 
                            (cond-predicate first)) 
                      (expand-clauses 
                       rest 
                       env)) 
             (make-if (cond-predicate first) 
                      (cond-actions first) 
                      (expand-clauses 
                        rest 
                        env))))))) 

davl

It's neater to just revise cond-actions into

  
 (define (cond-actions clause) 
   (if (eq? '=> (cadr clause)) 
     (list (list (caddr clause) (cond-predicate clause))) 
     (cdr clause)))