;;; For testing, something slow to calculate (define fibb (lambda (n) (cond ((= n 0) 1) ((= n 1) 1) (else (+ (fibb (- n 1)) (fibb (- n 2))))))) ;;; "Promise" = token which can be redeemed for a value, ;;; which is NOT CALCULATED until it is asked for. ;; API: ;; (promise-delay (lambda () BIG-CALCULATION)) -> PROMISE ;; (promise-force PROMISE) -> VAL (define promise-delay-v1 (lambda (thunk) thunk)) (define promise-force-v1 (lambda (p) (p))) (define promise-delay (lambda (thunk) (let ((val-saved? #f) (saved-val 'unforced-promise)) (lambda () (if val-saved? saved-val (let ((v (thunk))) (set! saved-val v) (set! val-saved? #t) v)))))) (define promise-force (lambda (p) (p))) ;;; Stream = Lazy List ;;; API: ;;; (stream-car STREAM) -> val ;;; (stream-cdr STREAM) -> STREAM ;;; (stream-null? STREAM) -> BOOLEAN ;;; (stream-cons THUNK STREAM) -> STREAM ;;; representation: ;;; stream is promise, whose value is either ;;; () for empty stream, or (val . stream) for ;;; non-empty stream. (define stream-cons (lambda (thunk stream) (delay (cons (thunk) stream)))) (define stream-null? (lambda (stream) (null? (force stream)))) (define stream-car (lambda (stream) (car (force stream)))) (define stream-cdr (lambda (stream) (cdr (force stream)))) ;;; utility functions (define stream-take (lambda (n stream) (if (zero? n) () (cons (stream-car stream) (stream-take (- n 1) (stream-cdr stream)))))) ;;; would like to write: ;;; (define stream-of-1s ;;; (stream-cons (lambda () 1) ;;; stream-of-1s)) (define stream-of-1s (delay (cons 1 stream-of-1s))) (define natural-numbers (delay (cons 0 (stream-map (lambda (x) (+ x 1)) natural-numbers)))) (define stream-empty (delay ())) (define stream-map (lambda (f stream) (delay (if (stream-null? stream) stream-empty (cons (f (stream-car stream)) (stream-map f (stream-cdr stream))))))) (define stream-fibb-v1 (stream-map fibb natural-numbers)) (define stream-map/2 (lambda (f stream1 stream2) (delay (if (stream-null? stream1) stream-empty (cons (f (stream-car stream1) (stream-car stream2)) (stream-map/2 f (stream-cdr stream1) (stream-cdr stream2))))))) (define stream-fibb (delay (cons 1 (delay (cons 1 (stream-map/2 + stream-fibb (stream-cdr stream-fibb)))))))