SICP 3.5.4

June 5, 2021 11:48

Exercise 3.77

A straightforward way to solve this one is to just wrap the old version of the integrator with a let statement that forces the delayed integrand. There may be alternate approaches, but since we already have a version that works with a non-delayed argument, it may as well be re-used. That said, it’s not sufficient to drop it in as-is, since the procedure is recursive (for this reason we can’t simply call the old procedure). As we know from the previous exercises, recursion within an argument expansion can cause problems when streams are infinite. It must be changed to include a delay statement on the argument being passed.

Exercise 3.78

Each of the blocks in the diagram can be interpreted as a function, with the labels naming the streams used as input or the output of those functions. That allows the solver to be created quite similarly to the way the first solve function was created.

(define (solve-2nd a b y0 d-y0 dt)
  (define y (integral (delay dy) y0 dt))
  (define dy (integral (delay ddy) d-y0 dt))
  (define ddy (add-streams (scale-stream dy a)
                           (scale-stream y b)

Exercise 3.79

The implementation here is nearly identical to the specialized case. The only difference is that instead of the stream ddy being fully defined in advance, it will be formed by using the function passed as an argument, with a stream-map. It actually ends up being shorter, thanks to the power of stream-map with arbitrary arguments. The streams y and dy are the ones mapped to the function f. That allows any function of two arguments to be used, and the solver’s output will be a stream.

Exercise 3.80

As in the RC circuit, the functional blocks outline the structure; each can made into an internally defined procedure that generates the labeled streams for the block. The complication here is that the initial values are not known at the time the RLC procedure is run. If we defined the function block streams within RLC, we’d have to include some way to pass the initial values and generate the streams from them, possibly by passing the initial values along in the streams, or by having a ‘manager’/interface function that sets them as internal variables. My approach wraps all the block definitions inside the function that is returned. This way, they become internal not to RLC but to the stream-generating function that it returns. Producing the procedure’s output is not difficult either, as all that is needed once the internal streams are defined is the cons statement at the end to give the desired result.

Solutions 3.5.3