#lang racket (define natural-numbers (letrec ([next-nat (lambda (n) (lambda () (cons n (next-nat (+ 1 n)))))]) (next-nat 1))) (define (stream-map f stream) (define (next-stream-element s) (lambda () (let ([s-next (s)]) (cons (f (car s-next)) (next-stream-element (cdr s-next)))))) (next-stream-element stream)) ;; Can you define stream-filter? (define evens (stream-map (lambda (x) (* x 2)) natural-numbers)) (define odds (stream-map (lambda (x) (- x 1)) evens)) ;;;; Advanced Material ;; Combining streams with f (define (stream-zip-with f stream1 stream2) (define (next-stream-element s1 s2) (lambda () (let ([s1-next (s1)] [s2-next (s2)]) (cons (f (car s1-next) (car s2-next)) (next-stream-element (cdr s1-next) (cdr s2-next)))))) (next-stream-element stream1 stream2)) ;; Mind-blown: a stream of Fibonacci numbers (define fibs (lambda () (cons 0 (lambda () (cons 1 (stream-zip-with + fibs (cdr (fibs)))))))) (define (cache-thunk thunk) (let ([ans #f] [done #f]) (lambda () (if done ans (begin (set! ans (thunk)) (set! done #t) ans))))) (define (cache-stream stream) (define (next-stream-element s) (cache-thunk (lambda () (let ([s-next (s)]) (cons (car s-next) (next-stream-element (cdr s-next))))))) (next-stream-element stream)) (define (stream-of-sleeps) (cons (sleep 2) stream-of-sleeps)) ;; Try (cache-stream stream-of-sleeps) (define fibs2 (cache-stream (lambda () (cons 0 (lambda () (cons 1 (stream-zip-with + fibs2 (cdr (fibs2)))))))))