it's hard to make it stop! These problems are related. The structure of RANDOM-DRIVER is an infinite loop, as with all drivers. Because RANDOM-DRIVER never returns a value, there is no way to get an answer out without a side-effect like PRINT.
We can arrange to signal RANDOM-DRIVER that no more values are desired, and to return a value (see Figure N11).
(DEFINE (RANDOM-DRIVER F SEED)
(COND ((CAR F) (CDR F))
(T ((LAMBDA (NEWSEED)
(RANDOM-DRIVER ((CDR F) NEWSEED) NEWSEED))
((LAMBDA (Z)
(COND ((> Z 0) Z)
(T (+ Z -32768.))))
(* SEED 899.))))))
(DEFINE (GAUSSIAN G)
(WEBER 0 43 G))
(DEFINE (WEBER X N H)
(COND ((= N 0) (H X))
(T (CONS NIL
(LAMBDA (R)
(WEBER (+ X R) (- N 1) H))))))
(DEFINE (DRIVER USERFN)
(RANDOM-DRIVER (GAUSSIAN USERFN) 43))
Figure N11
"Gaussian" Random-Number Generator "Top Level" without Side Effects
Using this new definition, we can write:
(DEFINE (P R) (CONS T R))
(DRIVER P 11)
which eventually returns one "Gaussian" number. (Doing something with more than one "Gaussian" number takes a little more work...)
Notice that in order to make this work, RANDOM-DRIVER had to know an awful lot about its functional argument; a fairly complicated protocol had to be developed for handshaking. We might argue that this exercise, while it has indeed removed all obvious side effects, has somewhat tarnished the modularity of the RANDOM program. In any case, the structure of our final program is not exactly what we had in mind when we started.