Streams Contract is the same as pairs... (head (pair-stream x str)) = x
-
Upload
xinqian-jun -
Category
Documents
-
view
16 -
download
0
description
Transcript of Streams Contract is the same as pairs... (head (pair-stream x str)) = x
Streams
Contract is the same as pairs...
(head (pair-stream x str)) = x (tail (pair-stream x str)) = str
...but order of evaluation is different
(pair-stream x str) evaluates x immediately, delays evaluation of str
(tail str) forces evaluation of the tail
Lazy Evaluation
compute values only when neededimplement with special form delay
(delay expr) make a promise to evaluate expr when forced to
(force delayed-expr) collect on the promise
An infinite stream
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
(define (ones <stream>) (pair-stream 1 ones))
Compare
(define (ones <list>) (pair 1 ones))==> ???
An infinite stream
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
(define (ones <stream>) (pair-stream 1 ones))
Compare
(define (ones <list>) (pair 1 ones))==> error: unbound identifier ones
(pair-stream 1 ones)
=macro expansion=>
(make <pair-stream> head-stream: 1 tail-stream: (delay ones))
=macro expansion=>
(make <pair-stream> head-stream: 1 tail-stream: (method () ones))
==> (1 . {proc () ones})
(head ones) ==> (head-stream ones) ==> 1
(tail ones) ==> (force (tail-stream ones)) ==> (force {proc () ones}) ==> ({proc () ones}) ==> ones ==> (1 . {proc () ones})
so ones is its own tail
Natural numbers
(define integers-from (method ((n <integer>)) (pair-stream n (integers-from (inc n)))))
(integers-from 42)is the infinite stream(42 43 44 45 46 47 48 49 50 51 52 ...
(define (naturals <stream>) (integers-from 0))
naturalsis the infinite stream(0 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
(add-method filter (method ((test <boolean>) (s <stream>)) (cond ((empty? s) empty-stream) ((test (head s)) (pair-stream (head s) (filter test (tail s)))) (else: (filter test (tail s))))))
(define (divisible? <function>) (method ((x <integer>) (n <integer>)) (zero? (modulo x n))))
(define (divisible-by-3? <function>) (method ((x <integer>)) (divisible? x 3)))
(define (threes <stream>) (filter divisible-by-3? naturals))
this is the infinite stream (0 3 6 9 12 15 ...
(define (print-stream <function>) (method ((s <stream>)) (print (head s)) (print-stream (tail s))))(print-stream naturals)
What does (print-stream naturals) do?
Print 0, force the tail (integers-from (inc 0)) evaluate (inc 0) ==> 1 evaluate integers-from ==> (1 . {proc () (integers-from (inc 1))})Print 1, force the tail... (2 . {promise (integers-from (inc 2))})Print 2, force the tail... (3 . {promise (integers-from (inc 3))})Print 3, force the tail...
Sieve of Eratosthenes (300 BC)
• 2 is prime• a number n > 2 is prime iff
it is not divisible by any smaller prime
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 ...
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 ...
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 ...
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 ...
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 ...
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 ...
(define (sieve <function>) (method ((s <stream>)) (bind ((next-prime (head s))) ;head is prime (pair-stream next-prime (sieve ;recursively sieve tail after (filter ;removing all multiples of head (method ((x <integer>)) (not (divisible? x next-prime))) (tail s)))))))
(define (primes <stream>) (sieve (integers-from 2)))
(print-stream primes)2 3 5 7 11 13 17 19 23 ...
Componentwise addition of streams
(define (add-streams <function>) (method ((a <stream>) (b <stream>)) (cond ((empty-stream? a) b) ((empty-stream? b) a) (else: (pair-stream (+ (head a) (head b)) (add-streams (tail a) (tail b)))))))
(add-streams (a0 a1 a2 a3 ...) (b0 b1 b2 b3...))==> (a0+b0 a1+b1 a2+b2 a3+b3 ...)
Natural numbers revisited
(define (naturals <stream>) (pair-stream 0 (add-streams ones naturals)))
naturals = (0 1 2 3 4 5 6 7 8 9 10 11 12 ... ones = (1 1 1 1 1 1 1 1 1 1 1 1 1 ...
sum = (1 2 3 4 5 6 7 8 9 10 11 12 13 ...
Pair 0 onto the front and we get naturals back:
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
Fibonacci numbers
F(0) = 0F(1) = 1F(n) = F(n-1) + F(n-2) for n 2
(define (fibs <stream>) (pair-stream 0 (pair-stream 1 (add-streams fibs (tail fibs)))))
fibs = (0 1 1 2 3 5 8 13 21 34 ...(tail fibs) = (1 1 2 3 5 8 13 21 34 55 ...
sum = (1 2 3 5 8 13 21 34 55 89 ...
Pair 0 and 1 onto the front and we get fibs back:
fibs = (0 1 1 2 3 5 8 13 21 34 55 89 ...
A more efficient version
(define (fibs-from <function>) (method ((a <integer>) (b <integer>)) (pair-stream a (fibs-from b (+ a b)))))
(define (efficient-fibs <stream>) (fibs-from 0 1))
this version: O(n) to create the first n fibslast version: O(p^n) where p = (1+sqrt(5))/2
Divergent computations
It’s possible to create streams with nothing inthem that are not the empty stream—even worse, empty? can't detect them!
(define (lose <stream>) (filter odd? (filter even? naturals)))
Merge — merge two streams into one
Example: joint bank account
Dexter stream:1/1/98 23:59 deposit $5001/15/98 23:59 deposit $5002/1/98 23:59 deposit $5002/15/98 23:59 deposit $500...
Fran stream:1/3/98 10:36 withdraw $2001/7/98 14:15 withdraw $1501/10/98 15:44 withdraw $5001/19/98 9:05 withdraw $825...
Merge by date & time so that all transactionson the output stream are in the right order
merge account balances
Dexter
Fran