10.1.1 Encapsulation

It would be more useful to package the counter variable with the procedure that manipulates it. Then we could create as many counters as we want, each with its own counter variable to manipulate.

The Stateful Application Rule (from Section 9.2.2) suggests a way to do this: evaluating an application creates a new environment, so a counter variable defined an the application environment is only visible through body of the created procedure.

The make-counter procedure creates a counter object that packages the count variable with the procedure that increases its value:

(define (make-counter)
  ((lambda (count)
     (lambda () (set! count (+ 1 count)) count))
   0))

Each application of make-counter produces a new object that is a procedure with its own associated count variable. Protecting state so it can only be manipulated in controlled ways is known as encapsulation.

The count place is encapsulated within the counter object. Whereas the previous counter used the global environment to store the counter in a way that could be manipulated by other expressions, this version encapsulates the counter variable so the only way to manipulate the counter value is through the counter object.

An equivalent make-counter definition uses a let expression to make the initialization of the count variable clearer:

(define (make-counter)
  (let ((count 0))
    (lambda () (set! count (+ 1 count)) count)))

Figure 10.1 depicts the environment after creating two counter objects and applying one of them.

Figure 10.1: Environment produced by evaluating.