問題3-77〜78

「3.5.4 ストリームと遅延評価」に入りました。短いトピックですが、delayとforceに関する非常に興味深い内容が説明されています。まだまだ理解が曖昧なところもありますが、cons-streamの内部で行なわれているdelayに頼らなくても、明示的にdelayを定義することで、より柔軟なループ表現を定義することができるということを感じ取ることができました。
問題3-77。integral手続きを書き直します。元のバージョンだと、再帰的にintegralを呼び出す時に、(stream-cdr integral)をしていますが、ここをdelayして遅延オブジェクトとしておかないと、処理が止まらなくなってしまいます。

(define (integral delayed-integrand initial-value dt)
  (define int
    (cons-stream initial-value
                 (let ((integrand (force delayed-integrand)))
                   (if (stream-null? integrand)
                       the-empty-stream
                       (integral (delay (stream-cdr integrand))
                                 (+ (* dt (stream-car integrand))
                                    initial-value)
                                 dt)))))
  int)

(define (solve f y0 dt)
  (define y (integral (delay dy) y0 dt))
  (define dy (stream-map f y))
  y)

(stream-ref (solve (lambda (y) y) 1 0.001) 1000)
;=>2.716923932235896

問題3-78。問われている数式の意味はよくわかりませんでしたが、図3.35の信号の流れのダイアグラムを参考にしながら、下記のような手続きを定義しました。y,dy,ddyを定義し、そのストリームを構成する要素は、図で示されているインプット要素を組み合わせました。また、yの中で使うdyと、dyの中で使うddyを遅延オブジェクトとしました。ただ、数式的に何を意味しているのかという点については、深追いすることができませんでした。

(define (solve-2nd a b dt y0 dy0)
  (define y (integral (delay dy) y0 dt))
  (define dy (integral (delay ddy) dy0 dt))
  (define ddy (add-streams
               (scale-stream dy a)
               (scale-stream y b)))
  y)

(stream-ref (solve-2nd 1 1 0.001 1 1) 1000)
;=>3.793448578735687

問題3-79と問題3-80は飛ばしました。また、三章最後の二つの問題も飛ばすことにしました。