<< Previous exercise (3.74) | Index | Next exercise (3.76) >>


 (define (make-zero-crossings input-stream last-value last-avpt) 
   (let ((avpt (/ (+ (stream-car input-stream) last-value) 2))) 
     (cons-stream (sign-change-detetor avpt last-avpt) 
                            (make-zero-crossings (stream-cdr input-stream) 
                                                                 (stream-car input-stream) 


The above solution is correct. However, in my opinion the authors of SICP have made some superfluous and unnecessary choices for this exercise as well as this entire section on zero crossings: keeping track of the last value is completely unnecessary because you have the *next* values.

Hence, a smoothed make-zero-crossings requiring only the input-stream as an argument can be implemented like this:

 (define (stream-cadr s) 
   (stream-car (stream-cdr s))) 
 (define (stream-caddr s) 
   (stream-cadr (stream-cdr s))) 
 (define (average x y) (/ (+ x y) 2)) 
 (define (make-zero-crossings s) 
   (let ((val1 (stream-car s)) 
         (val2 (stream-cadr s)) 
         (val3 (stream-caddr s))) 
     (let ((avg1 (average val1 val2)) 
           (avg2 (average val2 val3))) 
        (sign-change-detector avg2 avg1) 
        (make-zero-crossings (stream-cdr s)))))) 

Or alternatively, using stream-map as in the previous exercise:

 (define (average-sign-change-detector x y z) 
   (let ((avg1 (average x y)) 
         (avg2 (average y z))) 
     (sign-change-detector avg2 avg1))) 
 (define (stream-cddr s) 
   (stream-cdr (stream-cdr s))) 
 (define (make-zero-crossings s) 
   (stream-map average-sign-change-detector s (stream-cdr s) (stream-cddr s))) 



 (let ((x x-val)) ((lambda (. args) <expr>) args-val)) 

is nothing else but the syntax sugar of

 ((lambda (x . args) <expr>) x-val args-val) 

,there are only style differences between whether passing "last value" explicitly.