Date: Wed, 3 Mar 2004 11:28:08 -0600
From: Alvaro Fernandez <[log in to unmask]>
But in C++/Java, there is _run-time_ dispatch also, correct?
Yes, but only on the single object the message is being sent to.
Two points:
-- Syntax: The current non-function-like message sending syntax
object.methodName(args...)
is probably the easiest to declare. Doing a function-like syntax
methodName(object, args...)
might make declarations sufficiently messy to be unappealing. Not
sure.
-- Semantics: run-time dispatch in C++/java on more than one argument
must be done by hand, usually by manual cascading:
graphic->draw(device, args...)
Uses runtime on object1 for generic object2
Rectangle::draw(Device device, args...) {
device->draw(this, args...);
}
PostScriptEngine::draw(Rectangle graphic, args...) {
...
}
Every type of graphic pretty much has to have a similar method
that draws itself on the device. Here's a problem. Suppose I
invent a Polygon graphic, and some devices have built-in ways to
do it, but for devices that don't, I can draw it as a series of
lines, independent of the device. In the above, what I have to do
is declare virtual method on Device that handles Polygon for the
generic case, and then override methods for the devices that have
built-in mechanisms. Conceptually this is wrong. It is the
Polygon that knows how to draw itself generically, not the device.
Switching the order of dispatches just moves the problem. And I
should be able to add such a Graphic without changing the
declarations/API of Device, a completely unrelated class. In a
generic function environment, the generic Polygon drawing method
would be supplied at the conceptually correct place: with the
Polygon implementation:
void draw(Device device, Polygon poly, args...) {...}
Again, although that looks like compile-time overloading, it is
intended to be run-time overloading; therein lies the difference.
(For what it's worth, I wrote a (toy-ish but sufficiently usable)
generic function package in C++ for the debugger I wrote.
Consider what "add values" means. It depends on the run-time
(within the debugger) type of three things: the types of the two
operands, and the semantics imposed by the selected language.
Adding an integer and an array do wildly different things in
Fortran than in C. integer+floating for any size integer and any
size floating generally converts the integer to the floating type
and then recurses on the two floating values. In Fortran, adding
a scalar to an array can generically call a generic
scaler<op>array routine passing the scalar, array and the op (the
"add values" generic function) (and the language) which then
recurses on "add values" using the language and (this time) two
scalars as it traverses the elements of the array.
This stuff is very powerful for the domains that really need it.
Single-object message sending just won't cut it.)
|