mirror of
https://github.com/correl/sicp.git
synced 2024-11-23 11:09:57 +00:00
3.5 WIP
This commit is contained in:
parent
a8bdee4a8c
commit
7ce42a62ad
1 changed files with 300 additions and 0 deletions
300
3-5.org
Normal file
300
3-5.org
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
#+TITLE: 3.5 - Streams
|
||||||
|
|
||||||
|
#+BEGIN_HTML
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
|
||||||
|
</script>
|
||||||
|
#+END_HTML
|
||||||
|
|
||||||
|
* Streams are Delayed Lists
|
||||||
|
#+begin_src scheme
|
||||||
|
(define (cons-stream a b)
|
||||||
|
(cons a (delay b)))
|
||||||
|
|
||||||
|
(define (stream-car s)
|
||||||
|
(car s))
|
||||||
|
|
||||||
|
(define (stream-cdr s)
|
||||||
|
(force (cdr s)))
|
||||||
|
|
||||||
|
(define the-empty-stream '())
|
||||||
|
|
||||||
|
(define (stream-ref s n)
|
||||||
|
(if (= n 0)
|
||||||
|
(stream-car s)
|
||||||
|
(stream-ref (stream-cdr s) (- n 1))))
|
||||||
|
|
||||||
|
(define (stream-map proc s)
|
||||||
|
(if (stream-null? s)
|
||||||
|
the-empty-stream
|
||||||
|
(cons-stream (proc (stream-car s))
|
||||||
|
(stream-map proc (stream-cdr s)))))
|
||||||
|
|
||||||
|
(define (stream-for-each proc s)
|
||||||
|
(if (stream-null? s)
|
||||||
|
'done
|
||||||
|
(begin (proc (stream-car s))
|
||||||
|
(stream-for-each proc (stream-cdr s)))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+begin_src scheme :tangle yes
|
||||||
|
;; ===================================================================
|
||||||
|
;; 3.5.1: Streams are Delayed Lists
|
||||||
|
;; ===================================================================
|
||||||
|
|
||||||
|
(define (display-stream s)
|
||||||
|
(stream-for-each display-line s))
|
||||||
|
|
||||||
|
(define (display-line x)
|
||||||
|
(newline)
|
||||||
|
(display x))
|
||||||
|
|
||||||
|
(define (stream-enumerate-interval low high)
|
||||||
|
(if (> low high)
|
||||||
|
the-empty-stream
|
||||||
|
(cons-stream
|
||||||
|
low
|
||||||
|
(stream-enumerate-interval (+ low 1) high))))
|
||||||
|
|
||||||
|
(define (stream-filter pred stream)
|
||||||
|
(cond ((stream-null? stream) the-empty-stream)
|
||||||
|
((pred (stream-car stream))
|
||||||
|
(cons-stream (stream-car stream)
|
||||||
|
(stream-filter pred
|
||||||
|
(stream-cdr stream))))
|
||||||
|
(else (stream-filter pred (stream-cdr stream)))))
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Exercise 3.50
|
||||||
|
Complete the following definition, which generalizes `stream-map' to
|
||||||
|
allow procedures that take multiple arguments, analogous to `map' in
|
||||||
|
section *Note 2-2-3::, footnote *Note Footnote 12::.
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define (stream-map proc . argstreams)
|
||||||
|
(if (<??> (car argstreams))
|
||||||
|
the-empty-stream
|
||||||
|
(<??>
|
||||||
|
(apply proc (map <??> argstreams))
|
||||||
|
(apply stream-map
|
||||||
|
(cons proc (map <??> argstreams))))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
;; -------------------------------------------------------------------
|
||||||
|
;; Exercise 3.50
|
||||||
|
;; -------------------------------------------------------------------
|
||||||
|
|
||||||
|
(define (stream-map proc . argstreams)
|
||||||
|
(if (stream-null? (car argstreams))
|
||||||
|
the-empty-stream
|
||||||
|
(cons-stream
|
||||||
|
(apply proc (map stream-car argstreams))
|
||||||
|
(apply stream-map
|
||||||
|
(cons proc (map stream-cdr argstreams))))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Exercise 3.51
|
||||||
|
In order to take a closer look at delayed
|
||||||
|
evaluation, we will use the following procedure, which simply
|
||||||
|
returns its argument after printing it:
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define (show x)
|
||||||
|
(display-line x)
|
||||||
|
x)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
What does the interpreter print in response to evaluating each
|
||||||
|
expression in the following sequence?(7)
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define x (stream-map show (stream-enumerate-interval 0 10)))
|
||||||
|
|
||||||
|
(stream-ref x 5)
|
||||||
|
|
||||||
|
(stream-ref x 7)
|
||||||
|
#+end_src scheme
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define x (stream-map show (stream-enumerate-interval 0 10)))
|
||||||
|
; 9
|
||||||
|
; 8
|
||||||
|
; 7
|
||||||
|
; 6
|
||||||
|
; 5
|
||||||
|
; 4
|
||||||
|
; 3
|
||||||
|
; 2
|
||||||
|
; 1
|
||||||
|
; 0
|
||||||
|
;Value: x
|
||||||
|
|
||||||
|
(stream-ref x 5)
|
||||||
|
;Value: 5
|
||||||
|
|
||||||
|
(stream-ref x 7)
|
||||||
|
;Value: 7
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
** Exercise 3.52
|
||||||
|
Consider the sequence of expressions
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define sum 0)
|
||||||
|
|
||||||
|
(define (accum x)
|
||||||
|
(set! sum (+ x sum))
|
||||||
|
sum)
|
||||||
|
|
||||||
|
(define seq (stream-map accum (stream-enumerate-interval 1 20)))
|
||||||
|
(define y (stream-filter even? seq))
|
||||||
|
(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
|
||||||
|
seq))
|
||||||
|
|
||||||
|
(stream-ref y 7)
|
||||||
|
|
||||||
|
(display-stream z)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
What is the value of `sum' after each of the above expressions is
|
||||||
|
evaluated? What is the printed response to evaluating the
|
||||||
|
`stream-ref' and `display-stream' expressions? Would these responses
|
||||||
|
differ if we had implemented `(delay <EXP>)' simply as `(lambda ()
|
||||||
|
<EXP>)' without using the optimization provided by `memo-proc'?
|
||||||
|
Explain
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#+begin_example
|
||||||
|
1 ]=> sum
|
||||||
|
;Value: 210
|
||||||
|
|
||||||
|
1 ]=> (stream-head y 10)
|
||||||
|
|
||||||
|
;Value 18: (210 204 200 182 174 144 132 90 74 20)
|
||||||
|
|
||||||
|
1 ]=> (display-stream z)
|
||||||
|
|
||||||
|
210
|
||||||
|
200
|
||||||
|
195
|
||||||
|
165
|
||||||
|
155
|
||||||
|
105
|
||||||
|
90
|
||||||
|
20
|
||||||
|
;Value: done
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
After the definition of =seq=, =sum= is equal to 210. It remains at
|
||||||
|
210 through the remainder of the operations.This would not be the
|
||||||
|
case if delay were not memoized, as without being so it would be
|
||||||
|
recalculated each time the items in the node were resolved, adding to
|
||||||
|
the value of =sum= each time, and changing the results captured by =y=
|
||||||
|
and =z=.
|
||||||
|
* 3.5.2 Infinite Streams
|
||||||
|
#+begin_src scheme :tangle yes
|
||||||
|
;; ===================================================================
|
||||||
|
;; 3.5.2: Infinite Streams
|
||||||
|
;; ===================================================================
|
||||||
|
|
||||||
|
(define (integers-starting-from n)
|
||||||
|
(cons-stream n (integers-starting-from (+ n 1))))
|
||||||
|
|
||||||
|
(define integers (integers-starting-from 1))
|
||||||
|
|
||||||
|
(define (divisible? x y) (= (remainder x y) 0))
|
||||||
|
|
||||||
|
(define no-sevens
|
||||||
|
(stream-filter (lambda (x) (not (divisible? x 7)))
|
||||||
|
integers))
|
||||||
|
|
||||||
|
(define (fibgen a b)
|
||||||
|
(cons-stream a (fibgen b (+ a b))))
|
||||||
|
|
||||||
|
(define fibs (fibgen 0 1))
|
||||||
|
|
||||||
|
(define (sieve stream)
|
||||||
|
(cons-stream
|
||||||
|
(stream-car stream)
|
||||||
|
(sieve (stream-filter
|
||||||
|
(lambda (x)
|
||||||
|
(not (divisible? x (stream-car stream))))
|
||||||
|
(stream-cdr stream)))))
|
||||||
|
|
||||||
|
(define primes (sieve (integers-starting-from 2)))
|
||||||
|
#+end_src
|
||||||
|
** Defining streams implicitly
|
||||||
|
#+begin_src scheme :tangle yes
|
||||||
|
(define ones (cons-stream 1 ones))
|
||||||
|
|
||||||
|
(define (add-streams s1 s2)
|
||||||
|
(stream-map + s1 s2))
|
||||||
|
|
||||||
|
(define integers (cons-stream 1 (add-streams ones integers)))
|
||||||
|
|
||||||
|
(define fibs
|
||||||
|
(cons-stream 0
|
||||||
|
(cons-stream 1
|
||||||
|
(add-streams (stream-cdr fibs)
|
||||||
|
fibs))))
|
||||||
|
(define (scale-stream stream factor)
|
||||||
|
(stream-map (lambda (x) (* x factor)) stream))
|
||||||
|
|
||||||
|
(define double (cons-stream 1 (scale-stream double 2)))
|
||||||
|
|
||||||
|
(define primes
|
||||||
|
(cons-stream
|
||||||
|
2
|
||||||
|
(stream-filter prime? (integers-starting-from 3))))
|
||||||
|
|
||||||
|
(define (prime? n)
|
||||||
|
(define (iter ps)
|
||||||
|
(cond ((> (square (stream-car ps)) n) true)
|
||||||
|
((divisible? n (stream-car ps)) false)
|
||||||
|
(else (iter (stream-cdr ps)))))
|
||||||
|
(iter primes))
|
||||||
|
#+end_src
|
||||||
|
*** Exercise 3.53
|
||||||
|
Without running the program, describe the elements of the stream
|
||||||
|
defined by
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define s (cons-stream 1 (add-streams s s)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
\[
|
||||||
|
\sum_{i=1}^\infty 2^i
|
||||||
|
\]
|
||||||
|
*** Exercise 3.54
|
||||||
|
Define a procedure `mul-streams', analogous to `add-streams', that
|
||||||
|
produces the elementwise product of its two input streams. Use this
|
||||||
|
together with the stream of `integers' to complete the following
|
||||||
|
definition of the stream whose nth element (counting from 0) is n + 1
|
||||||
|
factorial:
|
||||||
|
|
||||||
|
#+begin_src scheme
|
||||||
|
(define factorials (cons-stream 1 (mul-streams <??> <??>)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#+begin_src scheme :tangle yes
|
||||||
|
(define (mul-streams s1 s2)
|
||||||
|
(stream-map * s1 s2))
|
||||||
|
|
||||||
|
(define factorials (cons-stream 1 (mul-streams (add-streams ones integers) factorials)))
|
||||||
|
#+end_src
|
||||||
|
*** Exercise 3.55
|
||||||
|
Define a procedure `partial-sums' that takes as argument a stream S
|
||||||
|
and returns the stream whose elements are S_0, S_0 + S_1, S_0 + S_1 +
|
||||||
|
S_2, .... For example, `(partial-sums integers)' should be the stream
|
||||||
|
1, 3, 6, 10, 15, ....
|
Loading…
Reference in a new issue