sicp-ex-3.2



<< Previous exercise (3.1) | Index | Next exercise (3.3) >>


Igor Saprykin

Not quite according to the task (no mf procedure), but it works.

  
 (define make-monitored 
   (let ((count 0)) 
         (lambda (f) 
           (lambda (arg) 
                 (cond ((eq? arg 'how-many-calls?) count) 
                           ((eq? arg 'reset-count) 
                            (set! count 0) 
                            count) 
                           (else (set! count (+ count 1)) 
                                         (f arg))))))) 

pluies

A cleaner way, creating mf as suggested, in message-passing style:

  
 (define (make-monitored function) 
   (define times-called 0) 
   (define (mf message) 
     (cond ((eq? message 'how-many-calls?) times-called) 
           ((eq? message 'reset-count) (set! times-called 0)) 
           (else (set! times-called (+ times-called 1)) 
                 (function message)))) 
   mf) 

mvladic

This solution allows to monitor procedures that accepts multiple arguments:

  
 (define (make-monitored proc) 
   (let ((count 0)) 
     (lambda (first . rest) 
       (cond ((eq? first 'how-many-calls?) count) 
             ((eq? first 'reset-count) (set! count 0)) 
             (else (begin (set! count (+ count 1))  
                          (apply proc (cons first rest)))))))) 

Example:

 (define m+ (make-monitored +)) 
 (m+ 40 2) 
 42 
 (m+ 'how-many-calls?) 
 1 

flamingo

Without mf procedure, using lambda:

  
 (define (make-monitored f) 
   (let ((count 0)) 
     (lambda (arg) 
       (cond ((eq? arg 'how-many-calls?) count) 
             ((eq? arg 'reset-count) (set! count 0)) 
             (else (begin (set! count (+ count 1)) 
                          (f arg))))))) 

Example:

 (define s (make-monitored sqrt)) 
  
 (s 100) 
 10 
 (s 100) 
 10 
 (s 'how-many-calls?) 
 2 
 >>> 

Daniel-Amariei

  
  
  
 (define (make-accumulator acc) 
   (lambda (x)  
     (set! acc (+ acc x)) 
     acc)) 
  
  
 (define (make-monitored f) 
   (define calls (make-accumulator 0)) 
   (define (reset) (calls (- (calls 0)))) 
   (define (mf a) 
     (cond ((equal? a 'how-many-calls?) (calls 0)) 
           ((equal? a 'reset-count) reset) 
           (else (calls 1) (f a)))) 
   mf) 
  
 (define s (make-monitored sqrt)) 
 (s 100)  ;; 10 
 (s 144)  ;; 12 
 (s 'how-many-calls?) ;; 2