sicp-ex-3.50



<< Previous exercise (3.49) | Index | Next exercise (3.51) >>


meteorgan

  
  
 (define (stream-map proc . argstreams) 
   (if (stream-null? (car argstreams)) 
       the-empty-stream 
       (cons-stream 
         (apply proc (map stream-car argstreams)) 
         (apply stream-map  
                (cons proc (map stream-cdr argstreams)))))) 

argstreams is a list of list, not a stream, we should not use stream-xxx procs on it.

 (define (stream-map proc . argstreams) 
   (if (stream-null? (car argstreams)) 
       the-empty-stream 
       (cons-stream 
        (proc (map car argstreams)) 
        (apply stream-map (cons proc (map cdr argstreams)))))) 

That implementation assumes that the streams are the same length (perhaps infinite). In order to cope with streams of different lengths I have this:

 (define (filter predicate list) 
   (cond ((null? list) 
          '()) 
         ((predicate (car list)) 
          (cons (car list) (filter predicate (cdr list)))) 
         (else 
          (filter predicate (cdr list))))) 
 (define (stream-map proc . argstreams) 
   (let ((non-null-args 
          (filter (lambda (s) (not (stream-null? s))) 
                  argstreams))) 
     (if (null? non-null-args) 
         the-empty-stream 
         (cons-stream 
          (apply proc (map stream-car non-null-args)) 
          (apply stream-map 
                 (cons proc (map stream-cdr non-null-args))))))) 

A bit cleaner:

  
 (define (any? pred lst) 
   (cond ((null? lst) #f) 
         ((pred (car lst)) #t) 
         (else (any? pred (cdr lst))))) 
  
 (define (stream-map proc . streams) 
   (if (any? stream-null? streams) 
       empty-stream 
       (stream-cons 
        (apply proc (map stream-car streams)) 
        (apply stream-map 
               proc ; No need to cons proc and the result of map. 
               (map stream-cdr streams))))) 

to Beckett, i think argstream is a list of stream not list of list. so it is correct to map it by stream-xxx. (map each stream by stream-xxx)