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
|
||||
#+STARTUP: indent
|
||||
|
||||
#+BEGIN_HTML
|
||||
<script type="text/javascript"
|
||||
|
@ -7,6 +8,30 @@
|
|||
#+END_HTML
|
||||
|
||||
* 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
|
||||
(define (cons-stream a b)
|
||||
(cons a (delay b)))
|
||||
|
@ -66,7 +91,8 @@
|
|||
|
||||
#+end_src
|
||||
|
||||
** Exercise 3.50
|
||||
** Exercises
|
||||
*** 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::.
|
||||
|
@ -97,7 +123,7 @@ section *Note 2-2-3::, footnote *Note Footnote 12::.
|
|||
(cons proc (map stream-cdr argstreams))))))
|
||||
#+end_src
|
||||
|
||||
** Exercise 3.51
|
||||
*** 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:
|
||||
|
@ -123,26 +149,24 @@ expression in the following sequence?(7)
|
|||
|
||||
#+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)
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
;Value: 5
|
||||
|
||||
(stream-ref x 7)
|
||||
6
|
||||
7
|
||||
;Value: 7
|
||||
|
||||
#+end_src
|
||||
** Exercise 3.52
|
||||
*** Exercise 3.52
|
||||
Consider the sequence of expressions
|
||||
|
||||
#+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
|
||||
the value of =sum= each time, and changing the results captured by =y=
|
||||
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
|
||||
;; ===================================================================
|
||||
;; 3.5.2: Infinite Streams
|
||||
|
@ -230,7 +260,7 @@ and =z=.
|
|||
|
||||
(define primes (sieve (integers-starting-from 2)))
|
||||
#+end_src
|
||||
** Defining streams implicitly
|
||||
*** Defining streams implicitly
|
||||
#+begin_src scheme :tangle yes
|
||||
(define ones (cons-stream 1 ones))
|
||||
|
||||
|
@ -261,6 +291,7 @@ and =z=.
|
|||
(else (iter (stream-cdr ps)))))
|
||||
(iter primes))
|
||||
#+end_src
|
||||
** Exercises
|
||||
*** Exercise 3.53
|
||||
Without running the program, describe the elements of the stream
|
||||
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 +
|
||||
S_2, .... For example, `(partial-sums integers)' should be the stream
|
||||
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