[previous] [up] [next]     [index]
Next: Mutable Structures Up: Mutable Structures Previous: Structures from Functions

Mutable Functional Structures


(define (fm-make-posn x0 y0)
  (local ((define x y0) 
          (define y y0) 
          (define (service-manager msg) 
            (cond 
              [(symbol=? msg 'x) x] 
              [(symbol=? msg 'y) y] 
              [(symbol=? msg 'set-x) (lambda (x-new) (set! x x-new))] 
              [(symbol=? msg 'set-y) (lambda (y-new) (set! y y-new))] 
              [else (error 'posn ``...'')]))) 
    service-manager))

(define (fm-posn-x p) (p 'x))

(define (fm-posn-y p) (p 'y))

(define (fm-set-posn-x! p new-value) ((p 'set-x) new-value))

(define (fm-set-posn-y! p new-value) ((p 'set-y) new-value))

Figure: An implementation of posns with mutators


Together, sections [cross-reference] and [cross-reference] suggest that structures are mutable. That is, we should be able to change the values of some field in a structure. After all, we introduced the service managers in section [cross-reference] to hide state variables, not just ordinary variable definitions.

Figure [cross-reference] shows how a small change to the definitions of figure [cross-reference] turns the locally hidden variables into state variables. The modified service manager offers two services per state variable: one for looking up the current value and one for changing it.

Consider the following definition and expression:

(define a-posn (fm-make-posn 3 4))

(begin (fm-set-posn-x! a-posn 5) (+ (posn-x a-posn) 8))

Evaluating them by hand shows how structures change. Here is the first step:
  ... 
= 
  (define x-for-a-posn 3) 
  (define y-for-a-posn 4) 
  (define (service-manager-for-a-posn msg) 
    (cond 
      [(symbol=? msg 'x) x-for-a-posn] 
      [(symbol=? msg 'y) y-for-a-posn] 
      [(symbol=? msg 'set-x) 
       (lambda (x-new) (set! x-for-a-posn x-new))] 
      [(symbol=? msg 'set-y) 
       (lambda (y-new) (set! y-for-a-posn y-new))] 
      [else (error 'posn ``...'')])) 
  (define a-posn service-manager-for-a-posn)

(begin (fm-set-posn-x! a-posn 5) (+ (posn-x a-posn) 8))

It renames and lifts the local definitions from inside of fm-make-posn. Because the function definition doesn't change for the rest of the evaluation, we focus on just the variable definitions:

  (define x-for-a-posn 3)
  (define y-for-a-posn 4) 
  (begin 
    (fm-set-posn-x! a-posn 5) 
    (+ (posn-x a-posn) 8))

= (define x-for-a-posn 3) (define y-for-a-posn 4) (begin (fm-set-posn-x! service-manager-for-a-posn 5) (+ (posn-x a-posn) 8))

= (define x-for-a-posn 3) (define y-for-a-posn 4) (begin ((service-manager-for-a-posn 'set-x) 5) (+ (posn-x a-posn) 8))

= (define x-for-a-posn 3) (define y-for-a-posn 4) (begin (set! x-for-a-posn 5) (+ (posn-x a-posn) 8))

= (define x-for-a-posn 5) (define y-for-a-posn 4) (+ (posn-x a-posn) 8)

At this point, the definition of x-for-a-posn has been modified in the expected manner. From now on every reference to this state variable, which represents the (simulated) x field a-posn, stands for 5. Every further reference to x-for-a-posn produces 5.


Exercises

Exercise 40.2.1

Develop a functional representation for the following structure definition:

(define-struct boyfriend (name hair eyes phone))
such that the fields of the simulated structure can be changed. Solution

Exercise 40.2.2

Here is a modification of the function-based implementation of posn structures in exercise [cross-reference]:

(define (ffm-make-posn x0 y0)
  (local ((define x x0) 
          (define (set-x new-x) (set! x new-x)) 
          (define y y0) 
          (define (set-y new-y) (set! y new-y))) 
  (lambda (select) 
    (select x y set-x set-y))))

(define (ffm-posn-x a-ffm-posn) (a-ffm-posn (lambda (x y sx sy) x)))

(define (ffm-posn-y a-ffm-posn) (a-ffm-posn (lambda (x y sx sy) y)))

(define (ffm-set-posn-x! a-ffm-posn new-value) (a-ffm-posn (lambda (x y sx sy) (sx new-value))))

(define (ffm-set-posn-y! a-ffm-posn new-value) (a-ffm-posn (lambda (x y sx sy) (sy new-value))))

Demonstrate how to modify a structure like (ffm-make-posn 3 4) so that its y field contains 5Solution


[previous] [up] [next]     [index]
Next: Mutable Structures Up: Mutable Structures Previous: Structures from Functions

PLT