さかもとのブログ

つらつらと

SICP演習問題3.50~3.52

プロンプトの表示などでちょっと長いけれど載せちゃう.
delay, cons-streamはマクロで定義しなければいけないところではまった.
naoya_tさんのstream.scmを見て救われた.

;;exercise3.50
(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))))))

;;section3.5.1
(load "./stream2.scm") ;without memo-proc
(load "./stream.scm")  ;with    memo-proc

(display-stream (stream-enumerate-interval 0 10))
(define (enumerate-interval low high)
  (if (> low high)
      '()
      (cons low (enumerate-interval (+ low 1) high))))

;;exercise3.51
(define (show x)
  (display-line x)
  x)

(define x (stream-map show
                      (stream-enumerate-interval 0 10)))

;;with memo-proc
(stream-ref x 5)
;=>
;1
;2
;3
;4
;55
(stream-ref x 7)
;6
;77

;;without memo-proc
(stream-ref x 5)
;=>
;1
;2
;3
;4
;55
(stream-ref x 7)
;=>
;1
;2
;3
;4
;5
;6
;77
;前の結果が使えないので,すべて計算しなおす
  • 3.52

memo-procを使わないと結果がおかしくなってしまうのは,accumの計算の元となるsumの値がおかしくなってしまうから.
そのため,memo-procを使うdelayで

(stream-ref 7)

を,何度行っても同じ値が帰ってくるが,memo-procを使わないdelayでそれをやると実行するたびに値が変わってしまう.

;;exercise3.52
;;通常版
(use srfi-1)
(define sum 0)

(define (accum x)
  (set! sum (+ x sum))
  sum)

(define seq (map accum (enumerate-interval 1 20)))
;=> (1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210)

(define y (filter even? seq))
;=>(6 10 28 36 66 78 120 136 190 210)

(define z (filter (lambda (x) (= (remainder x 5) 0)) seq))
;=>(10 15 45 55 105 120 190 210)

;;stream版(with memo-proc)
(define sum 0)
(define (accum x)
  (set! sum (+ x sum))
  sum)

(define seq (stream-map accum
                        (stream-enumerate-interval 1 20)))
seq ;=> (1 . #<closure (memo-proc memo-proc)>)
sum ;=> 1

(define y (stream-filter even? seq))
y   ;=> (6 . #<closure (memo-proc memo-proc)>)
sum ;=> 6

(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
                         seq))
z   ;=> (10 . #<closure (memo-proc memo-proc)>)
sum ;=> 10

(stream-ref y 7)
;=> 136
(stream-ref y 3)
;=> 36
(display-stream z)
;=>
;10
;15
;45
;55
;105
;120
;190
;210done
sum ;=> 210

;;stream版(without memo-proc)
(define sum 0)
(define (accum x)
  (set! sum (+ x sum))
  sum)

(define seq (stream-map accum
                        (stream-enumerate-interval 1 20)))
seq ;=> (1 . #<closure (stream-map stream-map)>)
sum ;=> 1

(define y (stream-filter even? seq))
y   ;=> (6 . #<closure (stream-filter stream-filter)>)
sum ;=> 6

(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
                         seq))
z   ;=> (15 . #<closure (stream-filter stream-filter)>)
sum ;=> 15

(stream-ref y 7)
;=> 162
(stream-ref y 3)
;=> 54
(display-stream z)
;=>
;15
;180
;230
;305done
sum ;=> 362