SICP Exercise 3.52 sequence of stream expressions

Exercise 3.52.  Consider the sequence of expressions

(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)


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.

SOLUTION

The code and tests are here.

ANALYSIS & EXPLANATION


Note 1:

stream-enumerate-interval produces the stream (Let’s call it s):
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
seq produces the stream:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210
y produces:
6, 10, 28, 36, 66, 78, 120, 136, 190, 210
z produces:
10, 15, 45, 55, 105, 120, 190, 210

Note 2: In the Racket streams implementation, when a stream is constructed the evaluations of both the car and the cdr are delayed until ‘stream-car’ and ‘stream-cdr’ are executed.

(define sum 0)

s: Does not Exist
seq: Does not Exist
y: Does not Exist
z: Does not Exist
sum is 0

(define (accum x)
  (set! sum (+ x sum))
sum)

s: Does not Exist
seq: Does not Exist
y: Does not Exist
z: Does not Exist
sum is 0

(define seq (stream-map accum (stream-enumerate-interval 1 20)))

s: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 (Stream just constructed)
seq: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210 (Stream just constructed)
y: Does not Exist
z: Does not Exist
sum is 0

(define y (stream-filter even? seq))

s: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
seq: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210
y: 6, 10, 28, 36, 66, 78, 120, 136, 190, 210 (Stream just constructed)
z: Does not Exist
sum is 6

(define z (stream-filter (lambda (x) (= (remainder x 5) 0)) seq))

s: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
seq: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210
y: 6, 10, 28, 36, 66, 78, 120, 136, 190, 210 (Stream exists but not accessed yet)
z: 10, 15, 45, 55, 105, 120, 190, 210 (Stream just constructed)
sum is 10

(stream-ref y 7)

s: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
seq: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210
y: 6, 10, 28, 36, 66, 78, 120, 136, 190, 210
z: 10, 15, 45, 55, 105, 120, 190, 210 (Stream exists but not accessed yet)
sum is 136
Printed Response is 136

(display-stream z)

s: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
seq: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210
y: 6, 10, 28, 36, 66, 78, 120, 136, 190, 210
z: 10, 15, 45, 55, 105, 120, 190, 210
sum is 210
Printed Response is:

10, 15, 45, 55, 105, 120, 190, 210

To the last question on whether the responses will differ if 'delay' were implemented without memoization, the answer is that the value of 'sum' will be higher since 'accum' will be applied multiple more times. Specifically, after y is defined, 'sum' is 6 but when z is defined, due to the absence of memoization 'accum' will be applied again on the elements 1, 2 and 3 from the enumerated interval. So z will be a  different stream from when memoization is used. Additionally 'seq' changes every time it is accessed. 

The explanation is also here.

Comments

Popular posts from this blog

SICP Exercise 2.56 differentiation rule

SICP Exercise 1.28 (Miller-Rabin Test)

SICP Exercise 4.18 a alternative strategy for interpreting internal definitions