遅延評価を(ストリームの内部だけでなく)ストリームの外で使ってみましょう、という話。
遅延評価を使うとループのある回路を作れて、微分方程式も解ける。
(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) ))