Blob


1 (define (memo-proc proc)
2 (let ((already-run? false) (result false))
3 (lambda ()
4 (if already-run?
5 result
6 (begin (set! already-run? true)
7 (set! result (proc))
8 result)))))
10 (define-syntax mydelay
11 (rsc-macro-transformer
12 (let ((xfmr
13 (lambda (exp)
14 `(memo-proc (lambda () ,exp)))))
15 (lambda (e r)
16 (apply xfmr (cdr e))))))
18 (define (myforce delayed-object)
19 (delayed-object))
21 (define-syntax cons-stream
22 (rsc-macro-transformer
23 (let ((xfmr (lambda (x y) `(cons ,x (mydelay ,y)))))
24 (lambda (e r)
25 (apply xfmr (cdr e))))))
27 (define (stream-car s)
28 (car s))
29 (define (stream-cdr s)
30 (myforce (cdr s)))
31 (define stream-null? null?)
32 (define the-empty-stream '())
34 (define (integers-starting-from n)
35 (cons-stream n (integers-starting-from (+ n 1))))
37 (define (stream-ref s n)
38 (if (= n 0)
39 (stream-car s)
40 (stream-ref (stream-cdr s) (- n 1))))
41 (define (stream-map proc . argstreams)
42 (if (stream-null? (car argstreams))
43 the-empty-stream
44 (cons-stream
45 (apply proc (map stream-car argstreams))
46 (apply stream-map (cons proc (map stream-cdr argstreams))))))
47 (define (stream-for-each proc s)
48 (if (stream-null? s)
49 'done
50 (begin (proc (stream-car s))
51 (stream-for-each proc (stream-cdr s)))))
53 (define (stream-enumerate-interval low high)
54 (if (> low high)
55 the-empty-stream
56 (cons-stream
57 low
58 (stream-enumerate-interval (+ low 1) high))))
59 (define (stream-filter pred s)
60 (if (stream-null? s)
61 the-empty-stream
62 (let ((scar (stream-car s)))
63 (if (pred scar)
64 (cons-stream scar (stream-filter pred (stream-cdr s)))
65 (stream-filter pred (stream-cdr s))))))
67 (define (display-stream s)
68 (stream-for-each display-line s))
69 (define (display-line x)
70 (newline)
71 (display x))
73 (define (test-case actual expected)
74 (newline)
75 (display "Actual: ")
76 (display actual)
77 (newline)
78 (display "Expected: ")
79 (display expected)
80 (newline))
82 (define (integers-starting-from n)
83 (cons-stream n (integers-starting-from (+ n 1))))
84 (define integers (integers-starting-from 1))
86 (define (divisible? x y) (= (remainder x y) 0))
87 (define no-sevens
88 (stream-filter (lambda (x) (not (divisible? x 7)))
89 integers))
91 (define (fibgen a b)
92 (cons-stream a (fibgen b (+ a b))))
93 (define fibs (fibgen 0 1))
95 (define (sieve s)
96 (cons-stream
97 (stream-car s)
98 (sieve (stream-filter
99 (lambda (x)
100 (not (divisible? x (stream-car s))))
101 (stream-cdr s)))))
103 ;; (define primes (sieve (integers-starting-from 2)))
104 ;; (test-case (stream-ref primes 25) 101)
106 (define ones (cons-stream 1 ones))
107 (define (add-streams s1 s2)
108 (stream-map + s1 s2))
109 (define integers (cons-stream 1 (add-streams ones integers)))
110 ;; (test-case (stream-ref integers 15) 16)
112 (define fibs
113 (cons-stream 0
114 (cons-stream 1
115 (add-streams (stream-cdr fibs)
116 fibs))))
118 (define (scale-stream stream factor)
119 (stream-map (lambda (x)
120 (* x factor))
121 stream))
122 (define double (cons-stream 1 (scale-stream double 2)))
124 (define primes
125 (cons-stream
127 (stream-filter prime? (integers-starting-from 3))))
128 (define (prime? n)
129 (define (iter ps)
130 (cond ((> (square (stream-car ps)) n) true)
131 ((divisible? n (stream-car ps)) false)
132 (else (iter (stream-cdr ps)))))
133 (iter primes))
135 (define (mul-streams s1 s2)
136 (stream-map * s1 s2))
138 (define (partial-sums s)
139 (define sums
140 (cons-stream (stream-car s)
141 (add-streams sums
142 (stream-cdr s))))
143 sums)
145 (define (merge s1 s2)
146 (cond ((stream-null? s1) s2)
147 ((stream-null? s2) s1)
148 (else
149 (let ((s1car (stream-car s1))
150 (s2car (stream-car s2)))
151 (cond ((< s1car s2car)
152 (cons-stream
153 s1car
154 (merge (stream-cdr s1) s2)))
155 ((> s1car s2car)
156 (cons-stream
157 s2car
158 (merge s1 (stream-cdr s2))))
159 (else
160 (cons-stream
161 s1car
162 (merge (stream-cdr s1) (stream-cdr s2)))))))))
164 (define (test-stream-list stream list)
165 (if (null? list)
166 'done
167 (begin (display "A: ")
168 (display (stream-car stream))
169 (display " -- ")
170 (display "E: ")
171 (display (car list))
172 (newline)
173 (test-stream-list (stream-cdr stream) (cdr list)))))
175 (define (integrate-series a)
176 (stream-map / a integers))
178 (define exp-series
179 (cons-stream 1 (integrate-series exp-series)))
181 (define cosine-series
182 (cons-stream
184 (integrate-series (stream-map - sine-series))))
185 (define sine-series
186 (cons-stream
188 (integrate-series cosine-series)))
190 (define (mul-series s1 s2)
191 (cons-stream
192 (* (stream-car s1) (stream-car s2))
193 (add-streams
194 (scale-stream (stream-cdr s2) (stream-car s1))
195 (mul-series (stream-cdr s1) s2))))
197 (define (invert-unit-series s)
198 (define x
199 (cons-stream
201 (mul-series (stream-map - (stream-cdr s))
202 x)))
203 x)
205 (define (div-series num den)
206 (let ((den-car (stream-car den)))
207 (if (zero? den-car)
208 (error "Denominator has zero constant term -- DIV-SERIES")
209 (scale-stream
210 (mul-series
211 num
212 (invert-unit-series (scale-stream den (/ 1 den-car))))
213 (/ 1 den-car)))))
216 (define (sqrt-improve guess x)
217 (define (average x y)
218 (/ (+ x y) 2))
219 (average guess (/ x guess)))
221 (define (sqrt-stream x)
222 (define guesses
223 (cons-stream
225 (stream-map (lambda (guess)
226 (sqrt-improve guess x))
227 guesses)))
228 guesses)
229 ;; (test-stream-list (stream-map exact->inexact (sqrt-stream 2))
230 ;; '(1 1.5 1.4166 1.4142156 1.41421356))
232 (define (pi-summands n)
233 (cons-stream (/ 1 n)
234 (stream-map - (pi-summands (+ n 2)))))
235 (define pi-stream
236 (scale-stream (partial-sums (pi-summands 1)) 4))
237 ;; (test-stream-list (stream-map exact->inexact pi-stream)
238 ;; '(4 2.6667 3.4667 2.8952 3.3397))
240 (define (euler-transform s)
241 (let ((s0 (stream-ref s 0))
242 (s1 (stream-ref s 1))
243 (s2 (stream-ref s 2)))
244 (cons-stream
245 (- s2 (/ (square (- s2 s1))
246 (+ s0 (* -2 s1) s2)))
247 (euler-transform (stream-cdr s)))))
249 ;; (test-stream-list (stream-map exact->inexact (euler-transform pi-stream))
250 ;; '(3.1667 3.1333 3.1452 3.1397 3.1427))
252 (define (make-tableau transform s)
253 (cons-stream s
254 (make-tableau transform
255 (transform s))))
257 ;; (test-stream-list (stream-map exact->inexact (stream-map stream-car (make-tableau euler-transform pi-stream)))
258 ;; '(4 3.1667 3.1421 3.1459935 3.1415927140 3.145926539752927))
260 ;; Exercise 3.63. Louis Reasoner asks why the sqrt-stream procedure was not written in the following more straightforward way, without the local variable guesses:
262 (define (sqrt-stream x)
263 (cons-stream 1.0
264 (stream-map (lambda (guess)
265 (sqrt-improve guess x))
266 (sqrt-stream x))))
268 ;; Alyssa P. Hacker replies that this version of the procedure is considerably less efficient because it performs redundant computation. Explain Alyssa's answer. Would the two versions still differ in efficiency if our implementation of delay used only (lambda () <exp>) without using the optimization provided by memo-proc (section 3.5.1)?
270 ;; by defining guesses, the procedure is able to take advantage of the fact that the previous terms in the stream have been calculated before. When mapping guesses, the delayed objects in the stream which have already been evaluated can simply return their memoized values. Without guesses, each new iteration would require the computation (from scratch) of each previous iteration.
272 ;; without the optimization, the two implementations would be equally inefficient