;3.67
(define (pairs s t)
(interleave
(stream-map (lambda (x) (list (stream-car s) x)
t))
(pairs (stream-cdr s) t)))
这里给出 一个 高人的解释 豁然开朗
Exercise 3.68. 答案
- 分析:
- (define (pairs s t)
- (interleave
- (stream-map (lambda (x) (list (stream-car s) x))
- t)
- (pairs (stream-cdr s) (stream-cdr t))))
复制代码
问题出在对 interleave 的调用和 pairs 的自引用上。
- interleave 是函数,所以先求值其参数,
- stream-map 调用 cons-stream,它是个宏,不对参数求值,所以能终止。
- 但 interleave 对第二个参数的求值 (pairs (stream-cdr s) (stream-cdr t)) 不会终止。它会不断调用 pairs,直到耗尽所有空间。
对比一下原来的 pairs
- (define (pairs s t)
- (cons-stream
- (list (stream-car s) (stream-car t))
- (interleave
- (stream-map (lambda (x) (list (stream-car s) x))
- (stream-cdr t))
- (pairs (stream-cdr s) (stream-cdr t)))))
复制代码
这里也存在 interleave 和 pairs,但此时是包含在一个 cons-stream 里的。cons-stream 是宏,不会对参数穷追猛打。 - 其实 Louis Reasoner 的方案比我们最初的方案更为自然。但由于 scheme 的函数调用是严格的,所以他的方案行不通。
如果我们更进一步,把 scheme 的函数调用也修改为惰性的,那么 Louis Reasoner 的方案就可行了。 用 lazy scheme 来试一下:
- #lang lazy
- (define (interleave s1 s2)
- (cons (car s1)
- (interleave s2 (cdr s1))))
- (define (pairs s t)
- (interleave
- (map (lambda (x) (list (car s) x))
- t)
- (pairs (cdr s) (cdr t))))
- (define (integers-starting-from n)
- (cons n (integers-starting-from (+ n 1))))
- (define integers (integers-starting-from 1))
复制代码
这里要使用 mzsheme 解释器。
- > (define x (pairs integers integers))
- > (display (take 10 x))
- ((1 1) (2 2) (1 2) (3 3) (1 3) (2 3) (1 4) (4 4) (1 5) (2 4))
|