2015/12/25
SICP 問題 4.18
本文中の変形であればうごく.
;; 3章で定義した手続きとマクロ
(define (integral integrand initial-value dt)
(define int
(cons-stream initial-value
(add-streams (scale-stream integrand dt)
int)))
int)
(define (stream-map proc . argstreams)
(if (stream-null? (car argstreams))
the-empty-stream
(cons-stream (apply proc (map stream-car argstreams))
(apply stream-map
(cons proc (map stream-cdr argstreams))))))
(define-syntax cons-stream
(syntax-rules ()
((_ a b) (cons a (delay b)))))
(define-syntax delay
(syntax-rules ()
((_ exp) (memo-proc (lambda () exp)))))
(define (solve f y0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (stream-map f y))
y)
;; 問題文の通りに変形すると,
(lambda (vars)
(let ((y '*unassigned*)
(dy '*unassigned*))
(let ((a (integral (delay dy) y0 dt))
(b (stream-map f y)))
(set! y a)
(set! dy b))
y))
;; まずはじめのletでyとvは``*unassigned*``に束縛される.
;; 次にaを束縛する.(integral ..)が評価される.dyはまだ*unassigned*だが,initial-valueだけcosされ,のこりの評価は遅れる.(delay dy)となっているのでdyもまだ評価されない.
;; 次にbを束縛する.(stream-map f y)を評価しようとするがこの時yはまだ'*unassigned*なのでエラー.
;; 本文中の変換をすると,
(lambda (vars)
(let ((y '*unassigned*)
(dy '*unassigned*))
(set! y (integral (delay dy) y0 dt))
(set! dy (stream-map f y))
y))
;; まずはじめに最初の式と同じようにyとdyを束縛する.
;; 次にyに(integral (delay dy) y0 dt)を代入する.
;; (integral ..)が評価される.dyはまだ*unassigned*だが,initial-valueだけcosされ,のこりの評価は遅れる.
;; (delay dy)となっているのでdyもまだ評価されない.
;; 次にdyに(stream-map f y)を代入する.この時点でyの値は(integral (delay dy) y0 dt).
;; stream-mapもはじめに必要なのはyの先頭の要素だけで,それはinitial-valueになっている.
;; その相互に呼び出しあいながらストリームが作られる.