Does anybody thought about having ...

lex at cc.gatech.edu lex at cc.gatech.edu
Mon Nov 22 18:35:48 UTC 2004


Short comments are at the top of this message; bigger ones at the end.


Brian Rice <water at tunes.org> wrote:
> > When I read the work on Cecil and MultiJava I do not see some really  
> > good example that make me say "Oh yes, I want this language feature!".
> 
> Research languages? You must be kidding! That's like getting an  
> impression about prototypes by looking at Self and Cecil - both of them  
> are research and don't leverage anything of theirs to create truly  
> comprehensive demonstrations of their power (that's another  
> discussion).
[...]
> My point is that multiple dispatch does not make a convincing  
> difference in the small. It makes a difference in the /large/, which  
> research systems like those can't demonstrate. 

Have you read through the Vortex compiler?  It is a hefty amount of
Cecil code and should not be dismissed.



> My canonical example is the generalized dimensioned-units library:
> 
> http://slate.tunes.org/cgi-bin/viewcvs.cgi/*checkout*/slate/src/lib/ 
> dimensioned.slate?rev=HEAD&sortby=date&content-type=text/plain
> 
> It is derived from a free Smalltalk library which had a huge amount of  
> double-dispatch and was prohibitive to work with. The Slate version had  
> Three Times fewer methods, and is actually something you can digest in  
> terms of the amount of information needed to understand an interaction.  
> It took me a few days just to get a correct overview of the system.

Impressive!



> When you're talking  
> about getting a lot of code into one system (even just picking  
> arbitrary pairs of things), the single-dispatch limitation just doesn't  
> add up. You need double-dispatch patterns, visitors, module annotations  
> to say that the method you're adding to class X really belongs in  
> module Y (see Squeak's recent method category notation system), and so  
> on and it all makes the curve more concave rather than flat in terms of  
> effort.

The cost of adding these patterns seems at most linear.  It takes linear
effort to begin with to add a double-dispatch method or a visitor
pattern, and once you've got it you can reuse it over and over. 
Further, the more you reuse them, the less the overhead is, and thus for
a larger program the overhead will tend to be lower than for a small
program.

Thus, I don't believe your argument that single-dispatch causes there to
be a lot more code -- much less a super-linear amount of code -- due to
having to manually implement dispatch code (double-dispatch and
visitors).

Also, I don't see any relevance with the method annotations.  Those are
simply markings of which methods go into which modules.  That is, they
are simply a way to cut apart a codebase at a small granularity.  I
don't see the relevance to the question of dispatch algorithms.




> Well, the reason fits in a nutshell. Do you like /having/ to always  
> define a method from exactly one perspective, and generalizing by  
> having to recurse through others' perspectives, or would you rather  
> just define the participation all at once? Once you start being able to  
> do this (you can still recurse when it's more sensible to organize code  
> that way, and we do), it adds up.


Yes, I do like having a built-in perspective for each method.  The way I
like to think of it is: I like that objects have common sense and can
take care of themselves.  I like that, when you send a message to an
object, the receiver object decides by itself which method will run. 
Further, this approach adds a nice opportunity for introducing
encapsulation: inside a method, you can delve into the innards of one
class, while outside it you cannot see any innards sat all.

Multiple dispatch changes this: now the choice of method is made by some
invisible dispatcher that is floating around behind the scenes.  Objects
no longer are fully in control of even their own methods.  I find this
disconcerting.  I wonder what happens with encapsulation.  And I wonder
if there might be software engineering issues with keeping separate
modules really separate, when multi-methods are spanning module
boundaries.



> It's the difference between having to write:
> 
> XCanvas draw: shape
> 	shape beDrawOnXCanvas: self
> (implement further method...)

I would call this drawOnXCanvas:, and I am fine with this pattern.  The
"onXCanvas" has to appear somewhere if we are really dispatching on
that, no matter what the exact dispatch mechanism is:

> canvas(must be an XCanvas) draw: triangle(must be a Triangle)
> (implement the method)

So not much code is saved.

Code saving is not the only argument though.  You also might argue about
which version is easier to work with.  I bet the multiple-dispatch
version is easier to learn to use, just because the alternative approach
(double dispatch) is anecdotally quite hard to learn.

Incidentally, a really compelling example of multiple dispatch for me is
when you develop 5-10 classes in close concert and then try to write
methods that work on groups of them.  In the above example, I am happy
to think of shapes and canvases being in separate modules, and thus I am
happy if they end up with some extra-loose connections between them. 
However, it is really annoying when the classes are clearly trying to
cooperate tightly with each other.  For example, in Chuck, when I wrote
the unionedWith: methods for combining two types into their union, it
would clearly have been nicer to write it out with multiple dispatch
than with the manual double-dispatching.

Such examples are not enough reason to add multiple dispatch to the
language, though, because they seem to be infrequent.  If there is a
high cost in giving up the idea of objects being in control of
themselves, then it is not worth a small improvement in code complexity
that doesn't happen very often.

On the other hand, there may be in-the-large issues with having
multi-methods scattered all around the codebase.  For example, I have
heard that the Vortex compiler's source code is hard to browse.  The
UWashington guys blame this difficulty on the lack of static typing and
other static organizing tools in the Cecil language, but it seems more
to me a combination of (a) using multi-methods, which seem prone to
exactly this problem, and (b) not having any sort of code browser other
than text editors.  A good browser would doubtless have helped with the
code being browsable, but how much?


-Lex



More information about the Squeak-dev mailing list