]> git.rkrishnan.org Git - sicp.git/blob - src/sicp/ex4_30.rkt
Solution to 4.30. Extremely enlightening!
[sicp.git] / src / sicp / ex4_30.rkt
1 #lang racket
2
3 (require "metacircular2-lazy.rkt")
4
5 (define env1 (make-environment))
6 (eval '(define (for-each proc items)
7          (if (null? items)
8              'done
9              (begin (proc (car items)) 
10                     (for-each proc (cdr items)))))
11       env1)
12 (eval '(for-each (lambda(x) (newline) (display x)) '(1 2 3)) env1)
13
14 #|
15
16 Part a.
17
18 One can observe the execution of this routine by a small modification to the 2 procedures that constitute
19 the lazy evaluator as follows (the only change is printing of the arguments)
20
21 (define (actual-value exp env)
22   (display (format "eval expr ~s~%" exp))
23   (newline)
24   (force-it (eval exp env)))
25
26 (define (force-it obj)
27   ;; (display (format "~s~%" obj))
28   (match obj
29     [`(thunk ,exp ,env) (begin
30                           (display (format "eval's output ~s~%" obj))
31                           (newline)
32                           (actual-value exp env))]
33     [_ obj]))
34
35 As we can observe during the execution, the `begin' gets transformed to `eval-sequence'
36 and then `newline' and `(display x)' are called. Both these are primitive expressions
37 and so the arguments are forced by apply.
38
39 The trace of the execution of the above definition and the evaluation are listed below.
40 |#
41
42 #|
43
44 eval expr for-each
45
46 eval expr (null? items)
47
48 eval expr null?
49
50 eval expr items
51
52 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
53
54 eval expr (quote (1 2 3))
55
56 eval expr proc
57
58 eval's output (thunk (lambda (x) (newline) (display x)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
59
60 eval expr (lambda (x) (newline) (display x))
61
62 eval expr newline
63
64
65 eval expr display
66
67 eval expr x
68
69 eval's output (thunk #0=(car items) (#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc #0#) (for-each proc (cdr items))))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))
70
71 eval expr (car items)
72
73 eval expr car
74
75 eval expr items
76
77 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
78
79 eval expr (quote (1 2 3))
80
81 1eval expr for-each
82
83 eval expr (null? items)
84
85 eval expr null?
86
87 eval expr items
88
89 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))
90
91 eval expr (cdr items)
92
93 eval expr cdr
94
95 eval expr items
96
97 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
98
99 eval expr (quote (1 2 3))
100
101 eval expr proc
102
103 eval's output (thunk proc (#hash((proc . (thunk (lambda (x) (newline) (display x)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))) (items . (thunk (quote (1 2 3)) #0#))) . #0#))
104
105 eval expr proc
106
107 eval's output (thunk (lambda (x) (newline) (display x)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
108
109 eval expr (lambda (x) (newline) (display x))
110
111 eval expr newline
112
113
114 eval expr display
115
116 eval expr x
117
118 eval's output (thunk #0=(car items) (#hash((proc . (thunk proc #3=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc #0#) (for-each proc #2=(cdr items))))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))) (items . (thunk #2# #3#))) . #1#))
119
120 eval expr (car items)
121
122 eval expr car
123
124 eval expr items
125
126 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))
127
128 eval expr (cdr items)
129
130 eval expr cdr
131
132 eval expr items
133
134 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
135
136 eval expr (quote (1 2 3))
137
138 2eval expr for-each
139
140 eval expr (null? items)
141
142 eval expr null?
143
144 eval expr items
145
146 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk proc #2=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))) (items . (thunk #0# #2#))) . #1#))
147
148 eval expr (cdr items)
149
150 eval expr cdr
151
152 eval expr items
153
154 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))
155
156 eval expr (cdr items)
157
158 eval expr cdr
159
160 eval expr items
161
162 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
163
164 eval expr (quote (1 2 3))
165
166 eval expr proc
167
168 eval's output (thunk proc (#hash((proc . (thunk proc #2=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #1=(cdr items))))) #0#)))))) (items . (thunk (quote (1 2 3)) #0#))) . #0#))) (items . (thunk #1# #2#))) . #0#))
169
170 eval expr proc
171
172 eval's output (thunk proc (#hash((proc . (thunk (lambda (x) (newline) (display x)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))) (items . (thunk (quote (1 2 3)) #0#))) . #0#))
173
174 eval expr proc
175
176 eval's output (thunk (lambda (x) (newline) (display x)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
177
178 eval expr (lambda (x) (newline) (display x))
179
180 eval expr newline
181
182
183 eval expr display
184
185 eval expr x
186
187 eval's output (thunk #0=(car items) (#hash((proc . (thunk proc #4=(#hash((proc . (thunk proc #3=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc #0#) (for-each proc #2=(cdr items))))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))) (items . (thunk #2# #3#))) . #1#))) (items . (thunk #2# #4#))) . #1#))
188
189 eval expr (car items)
190
191 eval expr car
192
193 eval expr items
194
195 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk proc #2=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))) (items . (thunk #0# #2#))) . #1#))
196
197 eval expr (cdr items)
198
199 eval expr cdr
200
201 eval expr items
202
203 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))
204
205 eval expr (cdr items)
206
207 eval expr cdr
208
209 eval expr items
210
211 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
212
213 eval expr (quote (1 2 3))
214
215 3eval expr for-each
216
217 eval expr (null? items)
218
219 eval expr null?
220
221 eval expr items
222
223 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk proc #3=(#hash((proc . (thunk proc #2=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))) (items . (thunk #0# #2#))) . #1#))) (items . (thunk #0# #3#))) . #1#))
224
225 eval expr (cdr items)
226
227 eval expr cdr
228
229 eval expr items
230
231 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk proc #2=(#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))) (items . (thunk #0# #2#))) . #1#))
232
233 eval expr (cdr items)
234
235 eval expr cdr
236
237 eval expr items
238
239 eval's output (thunk #0=(cdr items) (#hash((proc . (thunk (lambda (x) (newline) (display x)) #1=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc #0#)))) #1#)))))) (items . (thunk (quote (1 2 3)) #1#))) . #1#))
240
241 eval expr (cdr items)
242
243 eval expr cdr
244
245 eval expr items
246
247 eval's output (thunk (quote (1 2 3)) #0=(#hash((newline . (primitive #<procedure:newline>)) (false . #f) (cons . (primitive #<procedure:cons>)) (cdr . (primitive #<procedure:cdr>)) (display . (primitive #<procedure:display>)) (car . (primitive #<procedure:car>)) (/ . (primitive #<procedure:/>)) (null? . (primitive #<procedure:null?>)) (list . (primitive #<procedure:list>)) (+ . (primitive #<procedure:+>)) (true . #t) (= . (primitive #<procedure:=>)) (- . (primitive #<procedure:->)) (> . (primitive #<procedure:>>)) (* . (primitive #<procedure:*>)) (< . (primitive #<procedure:<>)) (for-each . (procedure (proc items) ((if (null? items) (quote done) (begin (proc (car items)) (for-each proc (cdr items))))) #0#)))))
248
249 eval expr (quote (1 2 3))
250
251 'done
252 |#
253
254 ;; part b
255 (define env2 (make-environment))
256 (eval '(define (p1 x)
257          (set! x (cons x '(2)))
258          x)
259       env2)
260 (eval '(define (p2 x)
261          (define (p e)
262            e
263            x)
264          (p (set! x (cons x '(2)))))
265       env2)
266 (eval '(p1 1) env2)
267 (eval '(p2 1) env2)
268
269 #|
270 With the original evaluator, we get '(1 2) since cons is a primitive and the argument x (a thunk) of cons
271 is forced, giving the value 1. The output of cons, which is '(1 2) is set as the new value of a variable x.
272 x is no longer a thunk at this point. Then x is eval'ed and returned.
273
274 In the second case, the argument of p2, x, is passed as a thunk. Now, the first statement, the definition
275 of the function p is defined. Now, this function is called with a (set! x ... ) in the second/final statement.
276 This statement is passed as a thunk (i.e. e is a thunk with expr (set! x ... )). As the first statement, e
277 is evaluated. e gets looked up and a thunk is returned. But the expr of thunk e is not evaluated. Now, we lookup
278 x and it is returned. x is the thunk with the expr `1'. This thunk is returned. If we don't force thunk in the 
279 repl (as in my examples where I call eval directly), what is returned is a thunk. x is not modified by the 
280 (set! x ...) because it is passed as thunk and has not been evaluated yet.
281
282 If we modify the eval-sequence according to Cy D's suggestions, then we get '(1 2) for both the statements. This is
283 because the first statement, e, gets forced, which makes the (set! x (cons x '(2))) to evaluate, creating the
284 side effect (x itself is a thunk, but gets forced because cons is a primitive). 
285
286 |#
287
288 ;; part c
289 #|
290
291 This is because the display function is a primitive and it forces the thunk anyway.
292
293 |#
294
295 ;; part d
296 #|
297
298 I like the approach in the text.
299
300 |#