26
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

Streams Contract is the same as pairs... (head (pair-stream x str)) = x

Embed Size (px)

DESCRIPTION

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. - PowerPoint PPT Presentation

Citation preview

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

merge

(1 2 3 5 6 9 10 12 17 18 19 20 ...

(1 3 6 12 17 18 20 ... (2 5 9 10 19 22 31 ...

(define (merge <function>) (method ((s1 <stream>) (s2 <stream>)) (cond ((empty? s1) s2) ((empty? s2) s1) ((< (head s1) (head s2)) (pair-stream (head s1) (merge (tail s1) s2))) (else: (pair-stream (head s2) (merge s1 (tail s2)))))))