ストリームについても尋ねます。たとえば、ストリーム ビルダーが定義されているここまたはここで使用される SICP スタイルのストリームを見つけることができます。from-By
;;;; Stream Implementation
(define (head s) (car s))
(define (tail s) ((cdr s)))
(define-syntax s-cons
(syntax-rules ()
((s-cons h t) (cons h (lambda () t)))))
;;;; Stream Utility Functions
(define (from-By x s)
(s-cons x (from-By (+ x s) s)))
このようなストリームの作成はマクロに依存しており、特別な方法でアクセスする必要があります。
(define (take n s)
(cond ; avoid needless tail forcing for n == 1 !
((= n 1) (list (head s))) ; head is already forced
((> n 1) (cons (head s) (take (- n 1) (tail s))))
(else '())))
(define (drop n s)
(cond
((> n 0) (drop (- n 1) (tail s)))
(else s)))
ただし、それらは永続的ではありません。つまりtake
、drop
アクセスごとに再計算されます。ストリームを永続化する 1 つの方法は、アクセス時に最後のコンス セルを外科的に変更するテーリング クロージャを作成することです。
(1 . <closure>)
(1 . (2 . <closure>))
....
このような:
(define (make-stream next this state)
(let ((tcell (list (this state)))) ; tail sentinel cons cell
(letrec ((g (lambda ()
(set! state (next state))
(set-cdr! tcell (cons (this state) g))
(set! tcell (cdr tcell))
tcell)))
(set-cdr! tcell g)
tcell)))
(define (head s) (car s))
(define (tail s)
(if (or (pair? (cdr s))
(null? (cdr s)))
(cdr s)
((cdr s))))
こんな風に使えるようになりました
(define a (make-stream (lambda (i) (+ i 1)) (lambda (i) i) 1))
;Value: a
a
;Value 13: (1 . #[compound-procedure 14])
(take 3 a)
;Value 15: (1 2 3)
a
;Value 13: (1 2 3 . #[compound-procedure 14])
(define b (drop 4 a))
;Value: b
b
;Value 16: (5 . #[compound-procedure 14])
a
;Value 13: (1 2 3 4 5 . #[compound-procedure 14])
(take 4 a)
;Value 17: (1 2 3 4)
a
;Value 13: (1 2 3 4 5 . #[compound-procedure 14])
では、 は何(make-stream (lambda (i) (list (cadr i) (+ (car i) (cadr i)))) car (list 0 1))
を定義しているのでしょうか。
更新: Daniel Friedmanの1994 年のスライド「The Joys of Scheme, Cont'd」では、これらの「メモ化されたストリーム」(そこで呼び出されているため) のより単純な実装が見つかり、tail
関数自体が強制ストリームをテール センチネルに格納します。なので
(define (tail s)
(if (or (pair? (cdr s))
(null? (cdr s)))
(cdr s)
(let ((n ((cdr s))))
(set-cdr! s n)
(cdr s))))
;; can be used as e.g. (https://ideone.com/v6pzDt)
(define fibs
(let next-fib ((a 0) (b 1))
(s-cons a (next-fib b (+ a b)))))