SICP問題3.81

乱数をresetする数値と、前の乱数の値からgenerateするための要求(今回はgenerateという文字列)からなるストリームを入力ストリームとして乱数のストリームを生成する手続き。
前の乱数の値から乱数を発生させるrand-updateはテスト用ですごく適当です。

(define (rand-stream s)
  (define random-init
    1) ; 適当
  (define (rand-update last-val)
    (+ last-val 1)) ; 超適当。ここは自分で考えたヤツで良いはず
  (define (rand-reset val)
    val)
  (define (req-result req last-val)
    (cond ((eq? req 'generate) (rand-update last-val))
          ((number? req) (rand-reset req))
          (else (error "Unknown request -- RAND" req))))
  (define (rand-sub req-stream last-val)
    (let ((new-val (req-result (car req-stream) last-val)))
      (cons-stream
       new-val
       (rand-sub (stream-cdr req-stream) new-val))))
  (rand-sub s random-init))

テスト用の入力ストリーム

(define test-list
  (list 'generate 5 'generate 'generate 10 14 2 3 5 'generate 'generate 'generate))
(define (make-test-stream org-list rest)
  (if (null? rest)
      (cons-stream (car org-list)
                   (make-test-stream org-list (cdr org-list)))
      (cons-stream (car rest)
                   (make-test-stream org-list (cdr rest)))))
(define test-request (make-test-stream test-list test-list))

テスト

(stream-ref-range test-request 0 20)
; generate
; 5
; generate
; generate
; 10
; 14
; 2
; 3
; 5
; generate
; generate
; generate
; generate
; 5
; generate
; generate
; 10
; 14
; 2
; 3
; #<undef>

; (stream-ref-range (rand-stream test-request) 0 20)
; 2
; 5
; 6
; 7
; 10
; 14
; 2
; 3
; 5
; 6
; 7
; 8
; 9
; 5
; 6
; 7
; 10
; 14
; 2
; 3
; #<undef>

rand-updateをどうにかすると、もう少しまともな感じになるかな。