2006/08/20

先日、Gauche のストリームと MIT Scheme のストリームがじゃっかん違う?と書いたんだけど、すみません僕が Gauche のドキュメントをちゃんと読んでなかっただけでした。具体的にはこのページ。

stream-delay
http://www.shiro.dreamhost.com/scheme/gauche/man/gauche-refj_158.html#IDX2975
"As a rule of thumb, any stream-producing functions should wrap the resulting expression by stream-delay."

これまで「Streamは遅延評価で実現する」という程度の認識しかなかった。それが SICP の "3.5.4 Streams and Delayed Evaluation" まで読み進んだところ、実際にはもっと込み入ってたってことがわかった。あいかわらずこの本は教科書としてスキがなさすぎ。つい鼻息が荒くなる。

で、そういう認識であらためて Gauche のドキュメントを見返すと、生成した stream を評価する順番を調整する stream-delay がちゃんと用意されてたってわけですよ。いっしゅん Gauche のわなかと思ったけど、ドキュメントを全部読んでないのと理解が甘いのが悪かっただけ。

Ex. 3.56 に当てはめると、
(define (merge s1 s2)
(stream-delay
(cond ((stream-null? s1) s2)
((stream-null? s2) s1)
(else
(let ((s1car (stream-car s1))
(s2car (stream-car s2)))
(cond ((< s1car s2car)
(stream-cons s1car
(merge (stream-cdr s1) s2)))
((> s1car s2car)
(stream-cons s2car
(merge s1 (stream-cdr s2))))
(else
(stream-cons s1car
(merge (stream-cdr s1)
(stream-cdr s2))))))))))

(define S (stream-cons
1
(merge (stream-scale S 2)
(merge (stream-scale S 3)
(stream-scale S 5)))))

gosh> (stream->list (stream-take S 100))
(1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36 40 45 48 50 54
60 64 72 75 80 81 90 96 100 108 120 125 128 135 144 150 160 162 180
192 200 216 225 240 243 250 256 270 288 300 320 324 360 375 384 400
405 432 450 480 486 500 512 540 576 600 625 640 648 675 720 729 750
768 800 810 864 900 960 972 1000 1024 1080 1125 1152 1200 1215 1250
1280 1296 1350 1440 1458 1500 1536)
ちゃんと求まる。

ついでに、347ページの微分方程式を解くプロシージャは次のようにすればいい。(そのまま Gauche で試すと 「stream-map に渡す y がstreamじゃねえ」と言われて実行できない)
(define (solve f y0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (stream-map f (stream-delay y)))
y)

No comments :