mirror of
https://github.com/correl/sicp.git
synced 2024-11-23 11:09:57 +00:00
3.5 with notes
This commit is contained in:
parent
7ce42a62ad
commit
4b9cf9c38b
1 changed files with 108 additions and 14 deletions
122
3-5.org
122
3-5.org
|
@ -1,4 +1,5 @@
|
||||||
#+TITLE: 3.5 - Streams
|
#+TITLE: 3.5 - Streams
|
||||||
|
#+STARTUP: indent
|
||||||
|
|
||||||
#+BEGIN_HTML
|
#+BEGIN_HTML
|
||||||
<script type="text/javascript"
|
<script type="text/javascript"
|
||||||
|
@ -7,6 +8,30 @@
|
||||||
#+END_HTML
|
#+END_HTML
|
||||||
|
|
||||||
* Streams are Delayed Lists
|
* Streams are Delayed Lists
|
||||||
|
** Notes
|
||||||
|
#+BEGIN_SRC scheme
|
||||||
|
(define x (delay 5))
|
||||||
|
|
||||||
|
;; is equivalent to
|
||||||
|
|
||||||
|
(define x (lambda () 5))
|
||||||
|
|
||||||
|
;; A "thunk" (a function of no arguments, used to delay evaluation of its return value)
|
||||||
|
|
||||||
|
(force x)
|
||||||
|
;; => 5
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
The MIT implementation of =delay= returns a =promise= value. Force
|
||||||
|
will evaluate a =promise= if it hasn't yet been computed. The result
|
||||||
|
of the evaluation will be memoized for future calls to force.
|
||||||
|
|
||||||
|
Stream processing explanation: [[https://www.youtube.com/watch?v%3Da2Qt9uxhNSM#t%3D48m00s][MIT OpenCourseWare Lecture 6A]]
|
||||||
|
|
||||||
|
A stream a sequence built as a pair of an initial value, and a
|
||||||
|
procedure to generate the next value and the next procedure to
|
||||||
|
continue the sequence.
|
||||||
|
** Code
|
||||||
#+begin_src scheme
|
#+begin_src scheme
|
||||||
(define (cons-stream a b)
|
(define (cons-stream a b)
|
||||||
(cons a (delay b)))
|
(cons a (delay b)))
|
||||||
|
@ -66,7 +91,8 @@
|
||||||
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Exercise 3.50
|
** Exercises
|
||||||
|
*** Exercise 3.50
|
||||||
Complete the following definition, which generalizes `stream-map' to
|
Complete the following definition, which generalizes `stream-map' to
|
||||||
allow procedures that take multiple arguments, analogous to `map' in
|
allow procedures that take multiple arguments, analogous to `map' in
|
||||||
section *Note 2-2-3::, footnote *Note Footnote 12::.
|
section *Note 2-2-3::, footnote *Note Footnote 12::.
|
||||||
|
@ -97,7 +123,7 @@ section *Note 2-2-3::, footnote *Note Footnote 12::.
|
||||||
(cons proc (map stream-cdr argstreams))))))
|
(cons proc (map stream-cdr argstreams))))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Exercise 3.51
|
*** Exercise 3.51
|
||||||
In order to take a closer look at delayed
|
In order to take a closer look at delayed
|
||||||
evaluation, we will use the following procedure, which simply
|
evaluation, we will use the following procedure, which simply
|
||||||
returns its argument after printing it:
|
returns its argument after printing it:
|
||||||
|
@ -123,26 +149,24 @@ expression in the following sequence?(7)
|
||||||
|
|
||||||
#+begin_src scheme
|
#+begin_src scheme
|
||||||
(define x (stream-map show (stream-enumerate-interval 0 10)))
|
(define x (stream-map show (stream-enumerate-interval 0 10)))
|
||||||
; 9
|
|
||||||
; 8
|
|
||||||
; 7
|
|
||||||
; 6
|
|
||||||
; 5
|
|
||||||
; 4
|
|
||||||
; 3
|
|
||||||
; 2
|
|
||||||
; 1
|
|
||||||
; 0
|
; 0
|
||||||
;Value: x
|
;Value: x
|
||||||
|
|
||||||
(stream-ref x 5)
|
(stream-ref x 5)
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
;Value: 5
|
;Value: 5
|
||||||
|
|
||||||
(stream-ref x 7)
|
(stream-ref x 7)
|
||||||
|
6
|
||||||
|
7
|
||||||
;Value: 7
|
;Value: 7
|
||||||
|
|
||||||
#+end_src
|
#+end_src
|
||||||
** Exercise 3.52
|
*** Exercise 3.52
|
||||||
Consider the sequence of expressions
|
Consider the sequence of expressions
|
||||||
|
|
||||||
#+begin_src scheme
|
#+begin_src scheme
|
||||||
|
@ -198,7 +222,13 @@ 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
|
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=
|
the value of =sum= each time, and changing the results captured by =y=
|
||||||
and =z=.
|
and =z=.
|
||||||
* 3.5.2 Infinite Streams
|
* Infinite Streams
|
||||||
|
** Notes
|
||||||
|
Streams can continue forever if the promise never returns an empty
|
||||||
|
stream.
|
||||||
|
|
||||||
|
Streams can be combined to model complex sequences.
|
||||||
|
** Code
|
||||||
#+begin_src scheme :tangle yes
|
#+begin_src scheme :tangle yes
|
||||||
;; ===================================================================
|
;; ===================================================================
|
||||||
;; 3.5.2: Infinite Streams
|
;; 3.5.2: Infinite Streams
|
||||||
|
@ -230,7 +260,7 @@ and =z=.
|
||||||
|
|
||||||
(define primes (sieve (integers-starting-from 2)))
|
(define primes (sieve (integers-starting-from 2)))
|
||||||
#+end_src
|
#+end_src
|
||||||
** Defining streams implicitly
|
*** Defining streams implicitly
|
||||||
#+begin_src scheme :tangle yes
|
#+begin_src scheme :tangle yes
|
||||||
(define ones (cons-stream 1 ones))
|
(define ones (cons-stream 1 ones))
|
||||||
|
|
||||||
|
@ -261,6 +291,7 @@ and =z=.
|
||||||
(else (iter (stream-cdr ps)))))
|
(else (iter (stream-cdr ps)))))
|
||||||
(iter primes))
|
(iter primes))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
** Exercises
|
||||||
*** Exercise 3.53
|
*** Exercise 3.53
|
||||||
Without running the program, describe the elements of the stream
|
Without running the program, describe the elements of the stream
|
||||||
defined by
|
defined by
|
||||||
|
@ -298,3 +329,66 @@ 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 +
|
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
|
S_2, .... For example, `(partial-sums integers)' should be the stream
|
||||||
1, 3, 6, 10, 15, ....
|
1, 3, 6, 10, 15, ....
|
||||||
|
* Exploiting the Stream Paradigm
|
||||||
|
** Notes
|
||||||
|
Streams and their property of delayed evaluation can be used to build
|
||||||
|
abstractions over the sequences and computations used to generate
|
||||||
|
them. The examples are the square-root stream and the pi streams being
|
||||||
|
accelerated via a generic stream transformation method.
|
||||||
|
|
||||||
|
* Streams and Delayed Evaluation
|
||||||
|
** Notes
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
...stream models of systems with loops may require uses of delay
|
||||||
|
beyond the “hidden” delay supplied by cons-stream.
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
Unfortunately, including delays in procedure calls wreaks havoc with
|
||||||
|
our ability to design programs that depend on the order of events,
|
||||||
|
such as programs that use assignment, mutate data, or perform input or
|
||||||
|
output.
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
As far as anyone knows, mutability and delayed evaluation do not mix
|
||||||
|
well in programming languages, and devising ways to deal with both of
|
||||||
|
these at once is an active area of research.
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
* Modularity of Functional Programs and Modularity of Objects
|
||||||
|
|
||||||
|
** Notes
|
||||||
|
Random number generation can be implemented as an infinite stream
|
||||||
|
instantiated with some seed.
|
||||||
|
|
||||||
|
*** A functional-programming view of time
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
We can model a changing quantity, such as the local state of some
|
||||||
|
object, using a stream that represents the time history of successive
|
||||||
|
states. In essence, we represent time explicitly, using streams, so
|
||||||
|
that we decouple time in our simulated world from the sequence of
|
||||||
|
events that take place during evaluation.
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
Events over time can be merged / serialized (deterministically?) into
|
||||||
|
a stream of events.
|
||||||
|
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
This is precisely the same constraint that we had to deal with in
|
||||||
|
3.4.1, where we found the need to introduce explicit synchronization
|
||||||
|
to ensure a “correct” order of events in concurrent processing of
|
||||||
|
objects with state. Thus, in an attempt to support the functional
|
||||||
|
style, the need to merge inputs from different agents reintroduces the
|
||||||
|
same problems that the functional style was meant to eliminate.
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
With a working merge solution, a system can be designed in a
|
||||||
|
functional way, operating on a stream of state and inputs.
|
||||||
|
|
||||||
|
The Erlang/OTP generic server, generic fsm and other behaviours are
|
||||||
|
implemented in such a way that input streams received concurrently are
|
||||||
|
merged by the vm and combined with the state of the process as a
|
||||||
|
single stream pairing the current state with the next input to
|
||||||
|
process, allowing an Erlang developer to build a functional interface
|
||||||
|
with the complexities of concurrency abstracted away.
|
||||||
|
|
Loading…
Reference in a new issue