4.4 Exercise 4.4
or and and can be implemented by direct evaluation in the
interpreter as follows:
(define (eval-and exps env) | (define (iter rest) | (cond ((null? rest) true) | (((car rest)) (iter (cdr rest))) | (else false))) | (iter (map (lambda (exp) (lambda () (eval exp env))) exps))) |
|
(define (eval-or exps env) | (define (iter rest) | (cond ((null? rest) false) | (((car rest) true)) | (else (iter (cdr rest))))) | (iter (map (lambda (exp) (lambda () (eval exp env))) exps))) |
|
Here, we follow the same pattern of creating a thunk evaluating to
the eval’d form of each expression (wrapped in a thunk in order
to simulate the lazy evaluation of the arguments to these special
forms) and iterating through them as much as is necessary to find
the answer.
Alternatively, we could translate each of them into a set of nested
if expressions:
(define (expand-and exps) | (if (null? exps) | true | (make-if (car exps) (expand-and (cdr exps)) 'false))) |
|
(define (expand-or exps) | (if (null? exps) | false | (make-if (car exps) 'true (expand-or (cdr exps))))) |
|
Here, expand-and and expand-or are procedures which
return syntactic objects that will evaluate to the correct
result. The way that this can work is by passing the first
expression as the predicate to if, and either resulting
in a constant value if we know the answer or an expression
computing the answer given the rest of the expressions if we
don’t. The latter can be accomplished by recursively calling
the expansion procedure.