我想知道如何使用替换模型来显示有关无限流的某些内容。例如,假设你有一个流将n放在第n个点,依此类推。我在下面定义它:
(define all-ints
(lambda ((n <integer>))
(stream-cons n (all-ints (+ 1 n)))))
(define integers (all-ints 1))
很明显,这可以做到它应该做的,但是有人会如何证明呢?我决定使用归纳法。具体来说,感应k在哪里
(last (stream-to-list integers k))
提供所提供的流的前k个值的最后一个值,在本例中为整数。我在下面定义了流到列表:
(define stream-to-list
(lambda ((s <stream>) (n <integer>))
(cond ((or (zero? n) (stream-empty? s)) '())
(else (cons (stream-first s)
(stream-to-list (stream-rest s) (- n 1)))))))
我特别想要证明的是k =(last(stream-to-list integer k))对于所有k&gt;的属性。 1.
获得基本案例相当容易,我可以做到这一点,但我将如何展示&#34;归纳案例&#34;尽可能彻底?由于计算第k + 1点的项目需要计算前面的k个项目,我不知道如何显示它。有人可以给我一些提示吗?
特别是,如果有人能够解释使用替换模型解释流的确切方式,我真的很感激。我知道他们必须与普通学生在流之前学会的其他结构不同,因为他们推迟计算,我觉得这意味着他们无法完全评估。反过来,我想,替代模型的应用eval apply等模式将不会被遵循。
答案 0 :(得分:2)
stream-cons
是一种特殊形式。它同样包含在lambdas中的两个参数,使它们成为thunk。像这样:
(stream-cons n (all-ints (+ 1 n))) ; ==>
(cons (lambda () n) (lambda () (all-ints (+ n 1))))
这些过程是使用词法范围进行的,所以这里n
是初始值,而强制尾部会在新的词法范围内再次调用all-ints
,给出新的n
然后在下一个stream-cons
中捕获。程序steam-first
和stream-rest
是这样的:
(define (stream-first s)
(if (null? (car s))
'()
((car s))))
(define (stream-rest s)
(if (null? (cdr s))
'()
((cdr s))))
现在所有这些都是半真半假。事实是它们不起作用,因为它们改变(记忆)值,因此相同的值不会被计算两次,但这对替换模型来说不是问题,因为副作用无论如何都是不受限制的。要了解它是如何完成的,请参阅SICP wizards in action。请注意,原始流只会延迟尾部,而现代流库会延迟头部和尾部。