; stream fundamentals (permitting frozen lists) ; cons$ is like cons except that it does not evaluate its second argument. ; A case can be made that cons should not even evaluate its first ; argument - See Friedman and Wise "Cons should not Evaluate its Arguments" ; **** car$ cdr$ cons$ **** ; rather like their list namesakes ; but cons$ does not evaluate its second argument ; It achieves this by surrounding the second arg with (lambda () ..) ; So cdr$ needs to apply this "thunk". ; Since the first argument to cons$ is -- in this version -- evaluated, ; car$ is identical to car. (define car$ car) (define cdr$ (lambda (x) ((cdr x)))) (define-syntax cons$ (syntax-rules () ((cons$ x y) (cons x (lambda () y))))) ; get the n'th member of a stream: (define nth$ (lambda (n x) (if (= 0 n) x (nth$ (- n 1) (cdr$ x))))) ; form the componentwise sum of two streams of numbers: (define +$ (lambda (s1 s2) (cons$ (+ (car$ s1) (car$ s2)) (+$ (cdr$ s1) (cdr$ s2))))) ; apply function f to each member of stream s (define map$ (lambda (f s) (cons$ (f (car$ s)) (map$ f (cdr$ s))))) ; make a new stream consisting of those members of s that satisfy ; predicate p: (define filter$ (lambda (p s) (if (p (car$ s)) (cons$ (car$ s) (filter$ p (cdr$ s))) (filter$ p (cdr$ s))))) ; print the first n members of stream s: (define printn$ (lambda (s n) (if (= 0 n) 'done (begin (printf "~s~%" (car$ s)) (printn$ (cdr$ s) (- n 1)))))) ; print the stream s, pausing after each 10 to ask the user if the ; printing should continue: (define print$ (lambda (s) (letrec ([printn (lambda (s n) (if (= 0 n) s (begin (printf "~s " (car$ s)) (printn (cdr$ s) (- n 1)))))] [printrow (lambda (s) (printf "~%Want more? ") (if (eq? (read) 'y) (printrow (printn s 10)) 'done))]) (printrow (printn s 10)))))