理系学生日記

おまえはいつまで学生気分なのか

問題 3-50 (3.5.1 Streams Are Delayed Lists)

ついに遅延評価の話に入りました.問題 3-40 くらいから,早く遅延評価の話にならないかなーと待ち望んでいた章ですね!

時間毎に変化する現実世界の事物を抽象化しようとすると,普通のプログラミングだと刻々と変化する状態を持つオブジェクトとして表現するわけですけど,別の考え方をすると,時間 t の関数として表現することもできます.t を離散化すると,結局一次元のリストとしても表せる.けど,やけにデカいリストになるし,未来永劫の値をリストに代入しとくわけにもいきません.そこで使うのが遅延評価ですよ!!
scheme だと,

(delay <exp> )

ってやると,後で exp を評価するって約束してくれる delayed-object が返ってくるんだってさ! そして,その約束を果たしてくれるように頼む

(force <delayed-object>)

も用意されている.これで,必要なときだけ評価させることができて,ウハウハです!

遅延評価を利用して stream が作れます.あくまでリストみたいなもんなんですけど,要素を取り出すときに初めて評価がされて要素ができるみたいな感じです.んじゃ,これで一般化 map を作るお! gauche には util.stream ライブラリに stream-map が既にあるけど,そんなの無視だお!

(use util.stream)

(define (stream-map proc . argstreams)
  (if (null? (car argstreams))
      stream-null
      (stream-cons
        (apply proc (map car argstreams))
        (apply stream-map
               (cons proc (map cdr argstreams))))))

よっしゃテストする!

(define ans (stream-map + (list 1 2 3) (list 4 5 6) (list 7 8 9)))
(stream-car ans)     ; 12
(stream-cadr ans)    ; 15
(stream-caddr ans)   ; 18

よっしゃいいかんじだ!

追記

次の問題を見ると,stream-map の引数も stream が期待されているみたいだなー.てことでこうなる.

(define (stream-map proc s)
  (if (stream-null? s)
      the-empty-stream
      (cons-stream (proc (stream-car s))
                   (stream-map proc (stream-cdr s)))))