Do you think Computer Science equals building websites and mobile apps? Are you feeling that you are doing repetitive and not so intelligent work? Are you feeling a bit sick about reading manuals and copy-pasting code and keep poking around until it works all day long? Do you want to understand the soul of Computer Science? If yes, read SICP!!!

Let’s do one more exercise.

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:

( define ( show x ) ( display-line x ) x )

What does the interpreter print in response to evaluating each expression in the following sequence?

( define x ( stream-map show ( stream-enumerate-interval 0 10 ))) ( stream-ref x 5 ) ( stream-ref x 7 )

This is easy, let’s just type the code into REPL and see what happens.

1 ] => ( define x ( stream-map show ( stream-enumerate-interval 0 10 ))) 0 ;Value: x 1 ] => ( stream-ref x 5 ) 12345 ;Value: 5 1 ] => ( stream-ref x 7 ) 67 ;Value: 7

Done. But I want to follow the execution step by step and see exactly what is happening. So let’s do it.

Starting with the first line of code:

( define x ( stream-map show ( stream-enumerate-interval 0 10 )))

Here is what happens by typing in that line of code:

( define x ( stream-map show ( stream-enumerate-interval 0 10 ))) ; First stream-enumerate-interval gets evaluated ( define x ( stream-map show ( cons-stream 0 ( stream-enumerate-interval 1 10 )))) ; Expand cons-stream since it is a macro ( define x ( stream-map show ( cons 0 ( delay ( stream-enumerate-interval 1 10 ))))) ; Expand delay since it is a macro ( define x ( stream-map show ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 )))))) ; We should expand memo-proc here but since it is rather long, expand it in your mind please ; Expand stream-map ( define x ( cons-stream ( show 0 ) ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 )))))))) ; Expand cons-stream since it is macro ( define x ( cons ( show 0 ) ( delay ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 ))))))))) ; Expand delay ( define x ( cons ( show 0 ) ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 )))))))))) ; print 0 here ( define x ( cons 0 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 ))))))))))

Now the second line

( stream-ref x 5 ) ; Put in x ( stream-ref ( cons 0 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 ))))))))) 5 ) ; Expand stream-ref ( stream-ref ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 )))))))))) 4 ) ; Expand stream-cdr and then force ( stream-ref (( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 ))))))))) 4 ) ; Expand memo-proc ( stream-ref ( stream-map show ( stream-cdr ( cons 0 ( memo-proc ( lambda () ( stream-enumerate-interval 1 10 )))))) 4 ) ; Expand stream-cdr ( stream-ref ( stream-map show (( memo-proc ( lambda () ( stream-enumerate-interval 1 10 ))))) 4 ) ; Expand memo-proc ( stream-ref ( stream-map show ( stream-enumerate-interval 1 10 )) 4 ) ; Expand stream-enumerate-interval ( stream-ref ( stream-map show ( cons-stream 1 ( stream-enumerate-interval 2 10 ))) 4 ) ; Expand cons-stream ( stream-ref ( stream-map show ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 ))))) 4 ) ; Expand stream-map ( stream-ref ( cons-stream ( show 1 ) ( stream-map show ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 ))))))) 4 ) ; Expand cons-stream ( stream-ref ( cons ( show 1 ) ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 ))))))))) 4 ) ; Print 1 here ( stream-ref ( cons 1 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 ))))))))) 4 ) ; Expand stream-ref ( stream-ref ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 )))))))))) 3 ) ; Expand stream-cdr ( stream-ref (( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 ))))))))) 3 ) ; Execute memo-proc ( stream-ref ( stream-map show ( stream-cdr ( cons 1 ( memo-proc ( lambda () ( stream-enumerate-interval 2 10 )))))) 3 ) ; Expand stream-cdr ( stream-ref ( stream-map show (( memo-proc ( lambda () ( stream-enumerate-interval 2 10 ))))) 3 ) ; Execute memo-proc ( stream-ref ( stream-map show ( stream-enumerate-interval 2 10 )) 3 ) ; Expand stream-enumerate-interval ( stream-ref ( stream-map show ( cons-stream 2 ( stream-enumerate-interval 3 10 ))) 3 ) ; Expand cons-stream ( stream-ref ( stream-map show ( cons 2 ( memo-proc ( lambda () ( stream-enumerate-interval 3 10 ))))) 3 ) ; Expand stream-map ( stream-ref ( cons-stream ( show 2 ) ( stream-map show ( stream-cdr ( cons 2 ( memo-proc ( lambda () ( stream-enumerate-interval 3 10 ))))))) 3 ) ; Expand cons-stream ( stream-ref ( cons ( show 2 ) ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 2 ( memo-proc ( lambda () ( stream-enumerate-interval 3 10 ))))))))) 3 ) ; Print 2 here ( stream-ref ( cons 2 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 2 ( memo-proc ( lambda () ( stream-enumerate-interval 3 10 ))))))))) 3 ) ; Let's speed up ; Print 3 here ( stream-ref ( cons 3 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 3 ( memo-proc ( lambda () ( stream-enumerate-interval 4 10 ))))))))) 2 ) ; Print 4 here ( stream-ref ( cons 4 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 4 ( memo-proc ( lambda () ( stream-enumerate-interval 5 10 ))))))))) 1 ) ; Print 5 here ( stream-ref ( cons 5 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 5 ( memo-proc ( lambda () ( stream-enumerate-interval 6 10 ))))))))) 0 ) ; Expand stream-ref ( stream-car ( cons 5 ( memo-proc ( lambda () ( stream-map show ( stream-cdr ( cons 5 ( memo-proc ( lambda () ( stream-enumerate-interval 6 10 ))))))))) 0 ) ; Expand stream-car 5

Phew! If you are still awake and reading here, maybe you should try to evaluate the third line of code. I have to go to sleep now so see you next time.