読者です 読者をやめる 読者になる 読者になる

(wat-aro)

無職から有職者にランクアップしました

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になっている.
;; その相互に呼び出しあいながらストリームが作られる.