<< Previous exercise (4.17) | Index | Next exercise (4.19) >>


 this won't work. because, in (let ((a <e1>) (b <e2>))), when compute e2, it depends y, but we only have a not y. For the same reason, the solution in text will work. 


I think both method will work, because (eval "dy") is 'delayed'.
But the expression "(stream-map f y)" defined in dy will be evaluated while y hasn't been defined yet.
So former method won't work.

Intitially, I too thought both methods would work, I can imagine a 'very lazy' implementation of stream-map the doesn't evaluate its arguments at all until the first element of the stream is requested.  But SICP's streams are definately not that lazy as they evaluate the first element of the stream immediately.  So y will be evaluated when (stream-map f y) is evaluated.

But even if that were the case, we would still need to have something to delay. We can't pass an object which doesn't exist to delay. That's why it can never work, under any evaluation model.

Note I'm talking here of evaluation models, the big problem here is not the lazy evaluation but the scope issue. let doesn't allow intercommunication of bindings. One would need to use let* or indeed the define version.


Previous one will work, the latter don't. Let's trace the latter definition of solve:

First, set both y and dy to *unassigned*, that's totally ok. Next, set a by something like

(y0 . (delay ..<something involved dy>.))

although dy is *unassigned*, since it's wrapped by delay, that ok.

Next, we want to set b by the evaluation of (stream-map f y), and here comes the problem.

By definition of stream-map, the result will be

((f (stream-car y)), (delay (stream-map ....)))))

but y is *unassigned* in current env now,thus evaluation of (f (stream-car y)) does not run correctly.