SICP 読み (128) 3.5.1 ストリームは遅延リスト

問題 3.52

複数の課題が提示されている。時間かかりそ。
まず sum の値と応答印字から。なるべく脳内変換を心掛けたいですが、控えも残す方向でやってみます。まず、以下に提示されている一連の式を。

gosh> (define sum 0)
sum
gosh> (define (accum x) (set! sum (+ x sum)) sum)
accum
gosh> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
seq
gosh> (define y (stream-filter even? seq))
y
gosh> (define z (stream-filter (lambda (x) (= (remainder x 5) 0)) seq))
z
gosh>

で、

(stream-ref y 7)
(display-stream z)

まで終了した時点での上記のナニ。とりあえず seq が define された時点で seq が束縛されるのは

(cons 1 (delay (stream-map accum 
			   (stream-cdr (cons 1 
					     (stream-enumerate-interval 2 20))))))

になりますな。ハズしてるかもしれんが長いし面倒なんでこう書く。

(cons 1 (delay (stream-map accum (force (delay (stream-enumerate-interval 2 20))))))

微妙。ちなみにこの時点でスデに accum の値は 1。

どんどん行く。y が define された時点で束縛されているのは以下の式。

(cons 2 
      (delay (stream-filter even?
			    (force 
			     (delay 
			       (stream-map accum
					   (force (delay
						    (stream-enumerate-interval 3 20)))))))))

わははは。ワケワカ。ちなみに sum の値は 3。
# 断言しちゃって良いのだろうか。

次は z の define ですな。5 で割り切れるか、という事なんで z には以下のリストが束縛される、と見ました。

(cons 5 
      (delay (stream-filter (lambda (x) (= (remainder x 5) 0))
			    (force 
			     (delay 
			       (stream-map accum
					   (force (delay
						    (stream-enumerate-interval 6 20)))))))))

で、sum の値は 15 になっているはず。

その次

stream-ref は C の配列なインデクスと同じ考え方なんで引数 7 なら 8 番目。なので stream-ref が戻すのは 16 になるはず。この時点での sum の値は 136 と見た。
次の display-stream が戻すのは

(5 10 15 20)

かなぁ。で、sum の値は 210 になる、と。

検証

gosh で試験してみたらこんなになった。何故だ。

gosh> (define sum 0)
sum
gosh> (define (accum x) (set! sum (+ sum x)) sum) 
accum
gosh> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
seq
gosh> sum
1
gosh> (define y (stream-filter even? seq))
y
gosh> sum
6
gosh> y
(6 . #<closure (memo-proc memo-proc)>)
gosh>

なんか stream-map とか stream-filter を勘違いしてるのかなぁ。あ、分かった。accum された値が、なのか。とほほほ。

再検討

gosh> (define sum 0)
sum
gosh> (define (accum x) (set! sum (+ x sum)) sum)
accum
gosh> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
seq

まず、ここでは sum は 1 で seq は (1 . #) です。てか y とか z に設定されるナニは普通のリストで言うとこんなになる訳ですね。

gosh> seq
(1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210)
gosh> y
(6 10 28 36 66 78 120 136 190 210)
gosh> z
(10 15 45 55 105 120 190 210)
gosh>

とほほほ。てコトは

gosh> (define y (stream-filter even? seq))
y

な時点では、sum は 6 (+ 1 2 3) で y は (6 . #) だし

gosh> (define z (stream-filter (lambda (x) (= (remainder x 5) 0)) seq))
z
gosh>

な時点では、sum は 10 (+ 1 2 3 4) で z は (10 . #) な訳か。落とし穴が一杯ですな。全然思慮深くないですね。< 自分

上記のリストから言えば (stream-ref y 7) は 136 が戻るか。あるいは (display-stream z) は上記のソレが出てくるという事になる。

それにしても馬鹿丸出しなんですが、このままエントリ投入。続きは別途。