sicp-ex-3.6



<< Previous exercise (3.5) | Index | Next exercise (3.7) >>


 (define rand 
   (let ((x random-init)) 
     (define (dispatch message) 
       (cond ((eq? message 'generate) 
               (begin (set! x (rand-update x)) 
                      x)) 
             ((eq? message 'reset) 
               (lambda (new-value) (set! x new-value))))) 
     dispatch)) 

Test:

 (define random-init 0) 
 (define (rand-update x) (+ x 1)) ; A not-very-evolved PNRG 
 (rand 'generate) 
 ; 1 
 (rand 'generate) 
 ; 2 
 ((rand 'reset) 0) 
 ; 0 
 (rand 'generate) 
 ; 1 

It's interesting to notice that the lambda returned by a call to (rand 'reset) still has the closure we created as lexical scope:

 x 
 ; Error: undefined variable 'x'. 

hi-artem

Here, inside (cond ..) construct, using "begin" is unnecessary.


Shawn

We could also define rand as a procedure instead of a variable:

  
 (define (rand arg) 
   (let ((x random-init)) 
     (cond ((eq? arg 'generate) 
            (set! x (rand-update x)) 
            x) 
           ((eq? arg 'reset) 
            (lambda (new-value) (set! x new-value)))))) 

pa3

Shawn's version will not work actually. It will always return the result of evaluating (rand-update random-input), because the state (x variable) is being recreated and reset to random-input each time rand function invoked.