You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.3 KiB
77 lines
2.3 KiB
|
|
Exercise 4.30: Cy D. Fect, a reformed C
|
|
programmer, is worried that some side effects may never take place, because the
|
|
lazy evaluator doesn’t force the expressions in a sequence. Since the value of
|
|
an expression in a sequence other than the last one is not used (the expression
|
|
is there only for its effect, such as assigning to a variable or printing),
|
|
there can be no subsequent use of this value (e.g., as an argument to a
|
|
primitive procedure) that will cause it to be forced. Cy thus thinks that when
|
|
evaluating sequences, we must force all expressions in the sequence except the
|
|
final one. He proposes to modify eval-sequence from 4.1.1
|
|
to use actual-value rather than eval:
|
|
|
|
|
|
(define (eval-sequence exps env)
|
|
(cond ((last-exp? exps)
|
|
(eval (first-exp exps) env))
|
|
(else
|
|
(actual-value (first-exp exps)
|
|
env)
|
|
(eval-sequence (rest-exps exps)
|
|
env))))
|
|
|
|
|
|
Ben Bitdiddle thinks Cy is wrong. He shows Cy the for-each procedure
|
|
described in Exercise 2.23, which gives an important example of a
|
|
sequence with side effects:
|
|
|
|
|
|
(define (for-each proc items)
|
|
(if (null? items)
|
|
'done
|
|
(begin (proc (car items))
|
|
(for-each proc
|
|
(cdr items)))))
|
|
|
|
He claims that the evaluator in the text (with the original
|
|
eval-sequence) handles this correctly:
|
|
|
|
|
|
;;; L-Eval input:
|
|
(for-each
|
|
(lambda (x) (newline) (display x))
|
|
(list 57 321 88))
|
|
57
|
|
321
|
|
88
|
|
|
|
;;; L-Eval value:
|
|
done
|
|
|
|
|
|
Explain why Ben is right about the behavior of for-each.
|
|
|
|
Cy agrees that Ben is right about the for-each example, but says that
|
|
that’s not the kind of program he was thinking about when he proposed his
|
|
change to eval-sequence. He defines the following two procedures in the
|
|
lazy evaluator:
|
|
|
|
|
|
(define (p1 x)
|
|
(set! x (cons x '(2))) x)
|
|
|
|
(define (p2 x)
|
|
(define (p e) e x)
|
|
(p (set! x (cons x '(2)))))
|
|
|
|
What are the values of (p1 1) and (p2 1) with the original
|
|
eval-sequence? What would the values be with Cy’s proposed change to
|
|
eval-sequence?
|
|
|
|
Cy also points out that changing eval-sequence as he proposes does not
|
|
affect the behavior of the example in part a. Explain why this is true.
|
|
|
|
How do you think sequences ought to be treated in the lazy evaluator? Do you
|
|
like Cy’s approach, the approach in the text, or some other approach?
|
|
|
|
|
|
|