示例:流的交错

讲解如何用 interleave 交错两条流,避免 stream-append 在无穷流上永远取不到第二条流元素的问题。

流的追加

假设你有两条流,想把它们合并成一条,类似于列表的 append。用 append,我们把一个列表的开头接到另一个列表的末尾。等价的流定义会是这样:

(define (stream-append s1 s2)
  (if (stream-null? s1)
      s2
      (cons-stream (stream-car s1)
                   (stream-append (stream-cdr s1) s2))))

但是等等!流的长度可能是无穷的!如果调用 (stream-append s1 s2) 时 s1 是无穷流,我们将永远无法访问 s2 的任何元素。

流的交错

另一种方案是把两条流交错(interleave)起来:

(define ones (cons-stream 1 ones)) ; (1 1 1 1 ...)
(define twos (cons-stream 2 twos)) ; (2 2 2 2 ...)

(define one-two (interleave ones twos)) ; (1 2 1 2 ...)

通过交错两条流,我们可以确保会用上来自两条流的元素。interleave 可以这样定义:

(define (interleave s1 s2)
  (if (stream-null? s1)
      s2
      (cons-stream (stream-car s1)
                   (interleave s2 (stream-cdr s1)))))