4.2.3 流作为推迟列表

4.2.3 流作为推迟列表
在3.5.1部分中,我们显示了如何实现流为一个延迟的列表.我们介绍了标识符
delay和cons-stream,它们允许我们组装一个对计算一个流的其它部分的承诺,直到稍后来
执行这个承诺.我们能使用介绍的标识符的通用技术来满足我们在解释过程
中的更多的控制,但这是困难的.第一件事,一个标识符不是像程序一样是
第一等公民,所以我们不能把它与高阶程序结合在一起.此外,我们必须
被强制创建流为一个新的数据对象的类型,与列表很相似,但是还不同.
为了使用流,这要求我们实现很多的普通列表的操作.(map,append等等)

在延迟的解释器中,流与列表是一样的,所以不需要为单独的列表与流操作
使用标识符.我们所需要做的是让cons 成为不限制严格的.完成这个任务的
一个方式是扩展推迟的解释器,来允许不限制严格的原生的程序,实现cons
作为其中之一。一个更简单的方式是重调用(2.1.3部分) 实现cons作为一个
原生的程序,并不是基本的需要。代替的是,我们能表示数对为程序:

(define (cons  x y)
(lambda  (m) (m  x  y)))

(define  (car z)  (z (lambda (p q)  p)))
(define  (cdr z)  (z (lambda (p q)  q)))

用这些基本的操作,列表操作的标准的定义能工作在无限的列表与
有限的列表上一样得好,流操作也能被实现作为列表操作,这是一些例子:

(define (list-ref items n)
   (if (= n 0)
        (car items)
 (list-ref (cdr items) (- n 1))
    )
)

(define (map proc items)
      (if (null? items) 
           '()
           (cons (proc (car items))
                 (map proc (cdr items))
            )
       )
)
(define (scale-list  items factor)
   (map  (lambda (x)  (* x factor))  items)
)
(define (add-lists list1 list2)
   (cond ((null? list1)  list2)
             ((null? list2)  list1)
      (else (cons (+  (car list1 ) (car list2))  (add-lists (cdr list1) (cdr list2))))
   )
)
(define ones (cons 1 ones))
(define integers (cons 1 (add-lists ones integers)))
;;;  L-eval  input:
(list-ref integers 17)
;;;  L-eval  value:
18

注意的是这些推迟列表现在甚至是更推迟的,比第三章中的流。列表的取表头,与取表尾
一样是推迟的。在事实上,甚至取一个推迟的列表的表头和表尾不需要强制一个列表的元素的值 。
这些值仅当它真得被需要时才强制。例如,作为一个原生的程序的参数,或者是被打印作为一个答案时。

推迟的列表也有3.5.4部分中的流的问题,当我们发现在公式化有循环的系统的流模型时
可能要我们在我们的程序中加上显式的推迟操作,除了我们要提供cons-stream.在推迟解释中,所有的程序
参数统一的推迟。例如,我们能实现程序,为了对列表求积分,或者是在3.5.4部分中作为我们的初始的目标,
求微分方程:

(define (integral integrand initial-value dt)
   (define int
             (cons inital-value
                                   (add-lists (scale-list integrand dt)
                                                        int)))
int)
(define (solve   f  y0  dt)
    (define  y (integral  dy  y0 dt))
    (define  dy (map   f  y))
    y
)
;;; L-Eval input:
(list-ref  (solve (lambda (x) x)  1 0.001)  1000)
;;; L-Eval value:
2.716924


练习4.32
给出一些例子,演示出第三章中的流与这部分中的所描述的推迟列表的区别。你能
如何利用这特殊的推迟性?

练习4.33
通过解释如下表达式,苯测试了推迟列表的如上的实现。

(car  '(a b c))

让他吃惊的是,这生成了错误。思考了一下后,他意识到通过读取引用的表达式中的列表,
不同于被 cons,car,cdr的新定义的列表操作。修改解释器的引用表达式的处理,为了在驱动
循环中输入的引用表达式能生成真正的推迟列表。

练习4.34
对于解释器修改它的驱动循环,为了推迟的数对和列表将能以某些合理的方式打印出来。
(关于无限的列表将如何做?)你可能需要修改推迟的数对的表示方法,为了解释器
能标识出它们,并且打印出它们。

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/82950159