まず,各ステップで sum の値はどうなっているのか!
(define sum 0) (define (accum x) (set! sum (+ x sum)) sum) (define seq (stream-map accum (stream-enumerate-interval 1 20))) (define y (stream-filter even? seq)) (define z (stream-filter (lambda (x) (= (remainder x 5) 0)) seq)) (stream-ref y 7) (display-stream z)
(stream-map accum (stream-enumerate-interval 1 20)) を実行する前はもちろん 0 な sum なんですけど,実行後にこの値は 1 になっています.これはもちろん,accum は stream-enumerate-interval の先頭要素 1 に対してしか評価されないからですね (stream-enumerate-interval 自体も 1 しか作らなくて,他は単に delayed-object になってるだけだけど).
(stream-filter even? seq) を評価すると,sum の値は 6 になっています.評価前の seq の状態は (1, delayed-objects) という形になっていますが,この中から偶数を探すために delayed-object が評価されていきます.delayed-object (delay stream-enumerate-interval) が評価されて,まず 2 が生成されまして,これが sum に足されます.そして次に,3 が stream の最初に設定されるときに,sum に 3 が足されるので,最終的に 1 + 2 + 3 = 6 になるというのが実情.
(stream-filter (lambda (x) (= (remainder x 5) 0))) が評価された後の sum の値は 10.もう stream の中で 1, 2, 3 は評価された後のものが memo 化されているだけですから,accum は呼び出されません.そのため,accum の呼び出しを伴うのは,stream-enumerate-interval によって 4 が生成されたとき.5 で 無名関数の値として #t が返るから,stream-filter の定義を返り見ると,6 までが生成されるわけで,この値は 6 + 4 + 5 + 6 = 21 になるはずなんだけど.わけわからん.