灯下 登录
计算机科学 / SICP / 4.2.2 An Interpreter with Lazy Evaluation

Exercise 4.31 · 习题

Exercise 4.31: The approach taken in this
section is somewhat unpleasant, because it makes an incompatible change to
Scheme. It might be nicer to implement lazy evaluation as an

upward-compatible extension, that is, so that ordinary Scheme
programs will work as before. We can do this by extending the syntax of
procedure declarations to let the user control whether or not arguments are to
be delayed. While we’re at it, we may as well also give the user the choice
between delaying with and without memoization. For example, the definition

(define (f a (b lazy) c (d lazy-memo))
…)

would define f to be a procedure of four arguments, where the first and

third arguments are evaluated when the procedure is called, the second argument

is delayed, and the fourth argument is both delayed and memoized. Thus,

ordinary procedure definitions will produce the same behavior as ordinary

Scheme, while adding the lazy-memo declaration to each parameter of

every compound procedure will produce the behavior of the lazy evaluator

defined in this section. Design and implement the changes required to produce

such an extension to Scheme. You will have to implement new syntax procedures

to handle the new syntax for define. You must also arrange for

eval or apply to determine when arguments are to be delayed, and

to force or delay arguments accordingly, and you must arrange for forcing to

memoize or not, as appropriate.

练习 4.31:本节所采用的做法有些不妥,因为它对 Scheme 做出了不兼容的改变。更好的做法或许是将惰性求值实现为一种向上兼容的扩展,即令普通 Scheme 程序仍能照常运行。我们可以通过扩展过程声明的语法来实现这一点,让用户控制各参数是否应被延迟求值。同时,还可以让用户选择延迟求值是否带记忆化。例如,定义

(define (f a (b lazy) c (d lazy-memo))
…)

将把 f 定义为一个四参数的过程,其中第一和第三参数在调用时立即求值,第二参数被延迟,第四参数既被延迟又带记忆化。这样,普通的过程定义将产生与普通 Scheme 相同的行为,而若对每个复合过程的每个参数都加上 lazy-memo 声明,则将产生本节所定义的惰性求值器的行为。请设计并实现产生这种 Scheme 扩展所需的修改。你需要实现新的语法过程来处理 define 的新语法,还需要安排 eval 或 apply 在适当时机确定各参数是否应被延迟,并相应地强迫求值或延迟求值,同时安排强迫求值是否带记忆化。

Racket #lang sicp
(define (f a (b lazy) c (d lazy-memo))
 …)