3.5.4 Streams and Delayed Evaluation

遅延評価を(ストリームの内部だけでなく)ストリームの外で使ってみましょう、という話。

遅延評価を使うとループのある回路を作れて、微分方程式も解ける。

実行はGaucheを用いた。SICPの例では

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

となってるけど、Gaucheではこれはうまくいかなくて

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

とする。

3.77 (integralの別バージョン)

(define (integral+ delayed-integrand initial-value dt)
  (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)))))

3.78 (2階微分方程式)

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

(stream-ref (solve-2nd 5 -4 0.001 1 1) 2000)
; => 7.381675653556238
(exp 2)
; => 7.38905609893065

3.79 (3.78の一般化)

(define (generalized-solve-2nd f dt y0 dy0)
  (define ddy (stream-map f dy y))
  (define dy (integral (delay ddy) dy0 dt))
  (define y (integral (delay dy) y0 dt))
  y)

(stream-ref (generalized-solve-2nd (lambda (a b) (+ (* 5 a) (* -4 b))) 0.001 1 1) 2000)
; => 7.381675653556238

3.80 (RLC直列回路)

(define (RLC R L C dt)
  (lambda (vC0 iL0)
    (define diL (add-streams (scale-stream vC (/ L))
                             (scale-stream iL (- (/ R L)))))
    (define dvC (scale-stream iL (- (/ C))))
    (define iL (integral (delay diL) iL0 dt))
    (define vC (integral (delay dvC) vC0 dt))
    (cons vC iL)
    ))