理系学生日記

おまえはいつまで学生気分なのか

問題 3-76 (3.5.3 Exploiting the Stream Paradigm)

3-75 のこの回答もやっぱしあんましよろしくなくて,何がよろしくないかというと,この一つの関数の中には「平滑化」を行う部分と「0 をまたがる遷移があるかどうか判断」という二つの機能が混じってしまっています.

(define (make-zero-crossings input-stream last-value last-avgt)
  (let ((avpt (/ (+ (stream-car input-stream) last-value) 2)))
    (cons-stream (sign-change-detector avpt last-avpt)
                 (make-zero-crossings (stream-cdr input-stream)
                                      (stream-car input-stream)
                                      avpt))))

そういうわけですから,まずは平滑化する関数を新たにつくる! 関数 smooth は連続する 2 つの要素の平均値をとったストリームを返してくれる関数になります.

(define (smooth s)
  (stream-map (lambda (a b) (/ (+ a b) 2))
              s
              (cons-stream 0 s)))

smooth を使えば平滑化の部分はもはや必要なくなります.そうすると,make-zero-crossings はもっと簡単に書き下せる!

(define (make-zero-crossings input-stream)
  (let ((smoothed-stream (smooth input-stream)))
    (stream-map zero-crossing 
                smoothed-stream
                (cons-stream 0 smoothed-stream))))

(define zero-crossings (make-zero-crossings sense-data))

非常にキレイだ!

追記

よくかんがえると,こっちのが良いよな.てか上のやつは題意みたしてないよな...

(define (make-zero-crossings input-stream)
  (stream-map zero-crossing 
              input-stream
              (cons-stream 0 input-stream)))

(define zero-crossings (make-zero-crossings (smooth sense-data)))