4.2 Variations on a Scheme: Lazy Evaluation-笔记

在元循环求值器的基础上,我们能够实现变体形式 惰性求值(lazy evaluation) 器。惰性求值器能够将程式参数包装为延迟计算的表达式,使参数在应用于程式时不会立即计算,而是在真正需要时才会进行计算。在之前实现的元循环求值器中参数真正被需要的情况包括下面三种:

  • 作为基础程式的参数时
  • 作为条件表达式的谓词时
  • 作为被应用的操作符时

在上述情况下需要将延迟计算的参数 强制执行(forcing) 产生参数值。要实现惰性求值器还需要 thunk 对象,通过 thunk 对象存储参数表达式和参数计算的环境,并在强制执行时取出表达式和环境进行计算。除此之外,thunk 对象还需要实现缓存功能以提高求值器的执行效率。当 thunk 对象实效强制执行时通过存储的表达式和环境计算结果,然后将 thunk 对象存储的表达式替换为计算结果,并修改 thunk 对象的标识使求值器能够知晓该 thunk 对象已经进行过计算;在随后此 thunk 对象被强制执行时不再进行计算,而是取出其中缓存的结果。

在惰性求值器基础上通过程式方式重新实现 cons 操作将获取惰性序对,然后通过惰性序对按标准定义重新实现列表的基础操作便能使用无限列表,其实此时的列表已经与流一样,而流也不需要再单独实现一套基础方法,由于它与列表的相似性完全可以使用此时列表的基础方法。cons 的程式实现如下。

(define (cons x y) (lambda (z) (z x y)))
(define (car z) (z (lambda (p q) p)))
(define (cdr z) (z (lambda (p q) q)))

如此一来,由于整个系统都是延迟计算的,也不需要为某些参数显式使用 delay 操作,避免了之前使用流时需要为某些参数显式使用 delay 的问题。另外,此时实现的列表比流更加惰性,因为即使通过 carcdr 获取元素,元素也没有产生计算结果,元素值只有在真正被需要时才会计算,比如应用于基础程式时或打印结果(此情况来源于求值器打印运算结果的设计)时。

你可能感兴趣的:(4.2 Variations on a Scheme: Lazy Evaluation-笔记)