In conventional style, the operators are represented as functions that know about the different types; the types themselves are just data. In Data-Directed-Programming, the operators and types are all data, and there is one universal operate function that does the work. We can also stand conventional style on its head, representing the types as functions and the operations as mere data.
In fact, not only are the types functions, but so are the individual data
themselves. That is, there is a function (make-circle
below) that represents
the circle type, and when you invoke that function, it returns a function that
represents the particular circle you give it as its argument. Each circle is
an object and the function that represents it is a dispatch procedure that
takes as its argument a message saying which operation to perform.
The new definitions of make-square
and make-circle
are below.
(define (make-square side)
(lambda (message)
(cond ((eq? message 'area)
(* side side))
((eq? message 'perimeter)
(* 4 side))
(else (error "Unknown message")))))
(define (make-circle radius)
(lambda (message)
(cond ((eq? message 'area)
(* pi radius radius))
((eq? message 'perimeter)
(* 2 pi radius))
(else (error "Unknown message")))))
(define square5 (make-square 5))
(define circle3 (make-circle 3))
Message passing may seem like an overly complicated way to handle this problem of shapes, but we'll see in the next lesson that it's one of the key ideas in creating object-oriented programming. Message passing becomes much more powerful when combined with the idea of local state that we'll learn next week.
We seem to have abandoned tagged data; every shape type is just some function,
and it's hard to tell which type of shape a given function represents. We
could combine message passing with tagged data, if desired, by adding a type
message that each object understands.
(define (make-square side)
(lambda (message)
(cond ((eq? message 'area)
(* side side))
((eq? message 'perimeter)
(* 4 side))
((EQ? MESSAGE 'TYPE) 'SQUARE)
(else (error "Unknown message")))))