(define make-counter (lambda (initial-val) (let ((count initial-val)) (lambda () (set! count (+ count 1)) count)))) (define c1 (make-counter 0)) (define c2 (make-counter 0)) (c1) => 1 (c2) => 1 (c1) => 2 (c1) => 3 (c2) => 2 (c1) => 4 (c2) => 3
One of the biggest problems with this method is that there is no way to rewind, or backtrack this iterator. Once you have called its inner procedure, you are stuck with the result.
This can be easily fixed by making the counter procedures take an optional argument (notice that I left out the superflous LET form and just use the original lambda argument):
(define (make-counter initial-value) (lambda optional-argument (if (and (pair? optional-argument) (eq? 'reset (car optional-argument))) (set! initial-value 0) (begin (set! initial-value (+ initial-value 1)) initial-value)))) > (define c1 (make-counter 0)) > (c1) 1 > (c1) 2 > (c1 'reset) > (c1) 1 > (c1) 2
It's easy from here to add different optional arguments for setting the internal state, or even retrieving different kinds of internal state. From there, it's only a small step to a message-passing object system, too...