流和替换模型

时间:2014-10-15 06:55:16

标签: stream scheme racket

我想知道如何使用替换模型来显示有关无限流的某些内容。例如,假设你有一个流将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等模式将不会被遵循。

1 个答案:

答案 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-firststream-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。请注意,原始流只会延迟尾部,而现代流库会延迟头部和尾部。