The Cows and Body Snatchers Example

The SICP problem 3.7, make-joint can be thought of as a superclass/subclass problem. If we were using an OOP language like Java, we would have a BankAccount class with a JointAccount subclass. Because we are using Scheme, the trick is to find a way to pass messages between dispatch procedures to get that effect.

The code, below, provides a mechanism for doing that. In this case, we have a make-cow class for creating cows and a make-body-snatcher subclass which, if it does not have a method for a particular message, passes the message up to the cow level. Examples of usage follow the class definitions.

; Cows can:
; * Report their names
; * Eat
; * Report their weights
; * Speak (MOO)
(define (make-cow name weight)
  (define (getName) name)
  (define (eat cud)
    (set! weight (+ weight (* 1/10 cud)))
    weight)
  (define (getWeight) weight)
  (define (speak) 'MOO!)
  (define (dispatch msg)
    (cond ((eq? msg 'name) getName)
          ((eq? msg 'eat) eat)
          ((eq? msg 'weight) getWeight)
          ((eq? msg 'speak) speak)))
  dispatch)

; Just like the cow except that when it speaks, it says MEOW
(define (make-body-snatcher cow)
  (define (speak) 'MEOW!)
  (define (dispatch msg)
    (cond ((eq? msg 'speak) speak)
          (else (cow msg))))
  dispatch)

And some usage...

> (define steveholt (make-cow 'steve-holt 1750))
> ((steveholt 'speak))
MOO!
> (define maebyfunke (make-body-snatcher steveholt))
> ((maebyfunke 'speak))
MEOW!
> ((maebyfunke 'weight))
1750
> ((maebyfunke 'eat) 100)
1760
> ((steveholt 'weight))
1760