Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Multiple dispatch in CLOS

22 views
Skip to first unread message

Kurt D. Fenstermacher

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to

I understand that CLOS supports multiple dispatch by enabling specialization
on multiple methods, and I know that Java and C++ (and other message-passing
OO systems) support only single dispatch. My question then is: what does
multiple dispatch in CLOS buy me that writing C++ functions that expect
multiple, typed arguments don't?

Suppose I write (in C++):
paint(Surface s, Tool brush)

This gives me a function that must match multiple arguments, just as CLOS
multimethod would. One obvious disadvantage of this is that I must determine
the types at compile-time. CLOS of course supports the more convenient
late-binding, but is that the only real distinction between multiple
dispatch and single dispatch? If so, why introduce new terminology (single
and multiple dispatch) when the old terminology works just fine (early vs.
late binding, or static vs. dynamic)?

Barry Margolin

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
In article <QGIU3.200$813.3810@uchinews>,

The intent was to distinguish it from OO systems like Smalltalk and
Flavors. They were based on message passing, and only the type of the
message receiver had any impact on the method selection. All of them are
based on late binding to the dynamic type; the difference is whether it
cares about the type of just the first argument or all of them; that's the
difference between single dispatch and multiple dispatch.

C++ and Java didn't exist at the time. C++'s dispatching based on the
static type of the arguments is generally referred to as "function
overloading".

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Christopher Browne

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
On Fri, 5 Nov 1999 16:16:48 -0600, Kurt D. Fenstermacher

<fens...@cs.uchicago.edu> wrote:
>I understand that CLOS supports multiple dispatch by enabling
>specialization on multiple methods, and I know that Java and C++ (and
>other message-passing OO systems) support only single dispatch. My
>question then is: what does multiple dispatch in CLOS buy me that
>writing C++ functions that expect multiple, typed arguments don't?

What multiple dispatch buys you is the ability to make methods
*independent* of class.

With C++ and Java, the methods are subservient to particular classes,
where you do things like

class foo {
/* data structures */
method a(); /* Unique to foo */
method b(); /* Unique to foo */
method c(); /* This function works like the one with bar */
}

class bar {
/* data structures */
method b(); /* Unique to foo */
method c(); /* Just like bar, but has to be repeated here as well */
method d(); /* Unique to foo */
}

With multiple dispatch schemes like CLOS, methods are defined in their
own right, and then may are *associated* with classes. With multiple
dispatch, the above example might look something more like:

class foo {
/* define data structures */
}
method a:foo () {}
method b:foo () {}

class bar {
/* define data structures */
}
method b:bar () {}
method d:bar () {}

method c() {} /* this code works with both classes foo and bar */

A sample that provides syntax looking more like C++ is thus:
<http://www.gwydiondylan.org/gdref/tutorial.html#MULTIPLE-DISPATCH>

The Dylan tutorial indicates: "Polymorphism, the specialization of
methods for use with particular classes, can be implemented by
declaring several methods with different parameters and attaching them
to one generic function."

The other critical aspect of multiple dispatch is that it allows you
to have multiple methods operating on the same object; they pass
control on from one to another so as to execute an appropriately
sequenced combination of generic and specific methods.
--
But what can you do with it? -- ubiquitous cry from Linux-user
partner. -- Andy Pearce, <a...@hpopd.pwd.hp.com>
cbbr...@ntlug.org- <http://www.hex.net/~cbbrowne/langlisp.html>

Erik Naggum

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
* Barry Margolin

| C++ and Java didn't exist at the time. C++'s dispatching based on the
| static type of the arguments is generally referred to as "function
| overloading".

very true, and what is being referred to as "single dispatch" in C++ is
actually calls to the virtual methods obtained with special syntax:
instance.method(...), so the argument employed by the requestor is a
request to compare apples and oranges, at best.

#:Erik

Marius Vollmer

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
cbbr...@news.hex.net (Christopher Browne) writes:

> What multiple dispatch buys you is the ability to make methods
> *independent* of class.

Hmm, I'd say that this does not follow. The notion of generic
functions is independent from whether they are multi-dispatch or just
single-dispatch. After all, single-dispatch is completely contained
within multi-dispatch. Generic functions are still independent from
classes even if their methods only specialize on one argument.

Mandating that methods be defined at the same time as the classes that
they specialize on (as C++ does it) is very inflexible and it is very
diffcult to feel at home again in the C++ straight jacket once you
know about generic functions.

I guess one of the fundamental errors in the design decisions of C++
was that they didn't want to change the linker. But they needed to do
that anyway for constructing global objects but then they didn't
realize what else the linker could do, like constructing vtables.

- Marius

Barry Margolin

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
In article <87aeorl...@zagadka.ping.de>,

Marius Vollmer <m...@zagadka.ping.de> wrote:
>Mandating that methods be defined at the same time as the classes that
>they specialize on (as C++ does it) is very inflexible and it is very
>diffcult to feel at home again in the C++ straight jacket once you
>know about generic functions.

Generic functions are independent of whether methods have to be declared in
class definitions. Smalltalk and Flavors use message passing, but new
methods can be defined anywhere.

james anderson

unread,
Nov 7, 1999, 3:00:00 AM11/7/99
to
?
isn't this distinction more that between generic functions and "slot-based"
functions, which is indepentant of the dispatching mechanims?

Christopher Browne wrote:
>
>...


>
> What multiple dispatch buys you is the ability to make methods
> *independent* of class.
>

Donald Fisk

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

"Kurt D. Fenstermacher" wrote:
>
> I understand that CLOS supports multiple dispatch by enabling specialization
> on multiple methods, and I know that Java and C++ (and other message-passing
> OO systems) support only single dispatch.

I don't know about C++ but I'm pretty sure Java does support multiple
dispatch, i.e. the method invoked depends on the parameter types as
well as the declaring class, and there can be more than one method
with the same name but with different parameter types in any class.

Java of course uses message passing, but multiple dispatch and
message passing are not mutually exclusive.

If anyone insists otherwise, I will check it again as it seems
to be as widespread a belief among non-Java programmers as "Lisp
is an interpreted language" is among non-Lisp programmers.

Le Hibou (ma propre opinion)

--
" |
Ceci n'est pas une pipe.
"
-- Daniel B. Case.

Jason Trenouth

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

Unfortunately, for Java programmers, the non-Java programmers are right. Java
dynamically dispatches only on the runtime type of the first argument. The
method invoked can depend on the other arguments but these determine which
method is invoked at compile-time. Doubly unfortunately, for Java programmers,
they often still have to declare the base type even for the first argument.
e.g.
// Java
ListIterator it = myList.listIterator();
while (it.hasNext()) {
((MyClass)it.next()).myMethod();
}

Note the cast when extracting the value from the list, if you can see it among
the iteration debris that is. Compare this with Common Lisp:

;; Common Lisp
(loop for x in my-list
do (my-method x))

;; or
(dolist (x my-list)
(my-method x))

;; or
(mapc 'my-method my-list)

Or Dylan:

// Dylan
for (x in my-list)
my-method(x)
end;

// or
do(my-method, my-list)

Thank goodness for Java, eh?

__Jason

David Hanley

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

Donald Fisk wrote:

> "Kurt D. Fenstermacher" wrote:
> >
> > I understand that CLOS supports multiple dispatch by enabling specialization
> > on multiple methods, and I know that Java and C++ (and other message-passing
> > OO systems) support only single dispatch.
>
> I don't know about C++ but I'm pretty sure Java does support multiple
> dispatch, i.e. the method invoked depends on the parameter types as
> well as the declaring class, and there can be more than one method
> with the same name but with different parameter types in any class.

Not really. In java this is handled by static overloading. For example,
you can do this:

class c
{
int foo( int a );
int foo( float f );
}

However, this is statically resolved. So, for example in this case:

class A { };
class B extends A { };

class c
{
int foo( A a );
int foo( B b );
}

A a = new B();
(new C()).foo( a );

will call the function for A not for B.

My understanding of what multiple dispatch buys you is it lets you
define, in a much more modular fashion, interaction between objects.
For example, in Java if you have objects A B C and D, you might
want to compare them, with, say, an equals method. You need to
code it like this:

Class a
{
int equals( BaseType co )
{
if ( co instanceof A )
{
}
else if ( co instanceof B )
{
}
}
}

Add a new class, and you have to go modify all the others. This
doesn't seem right, and begs the question of who should really own
comparisons. In CLOS, the following is the pattern:

(defmethod compare( (o1 A) (o2 A)) .. )

(defmethod compare( (o1 A)( o2 B)) .. )

A better system, IMO. There are more complex arguments for
the positive merits of multiple dispatch.

dave


Donald Fisk

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

Jason Trenouth wrote:
>
> On Mon, 08 Nov 1999 12:16:20 +0100, Donald Fisk <donal...@inthan.be> wrote:

> > I don't know about C++ but I'm pretty sure Java does support multiple
> > dispatch, i.e. the method invoked depends on the parameter types as
> > well as the declaring class, and there can be more than one method
> > with the same name but with different parameter types in any class.

> Unfortunately, for Java programmers, the non-Java programmers are right. Java


> dynamically dispatches only on the runtime type of the first argument.

By "first argument" do you mean the object the message is sent to, or
the first parameter?

> The
> method invoked can depend on the other arguments but these determine which
> method is invoked at compile-time.

Looks like we're using different definitions of multiple dispatch from
each
other. What I mean is that a.foo(b, c) and a.foo(d, e) can call
different
methods, both called foo and both belonging to the class of a, provided
b
and d belong to different classes or c and e belong to different
classes.
It may well be that the classes need to be known to the compiler -- I'll
check this.

> __Jason

Marco Antoniotti

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to
Donald Fisk <donal...@inthan.be> writes:

> "Kurt D. Fenstermacher" wrote:
> >
> > I understand that CLOS supports multiple dispatch by enabling specialization
> > on multiple methods, and I know that Java and C++ (and other message-passing
> > OO systems) support only single dispatch.
>

> I don't know about C++ but I'm pretty sure Java does support multiple
> dispatch, i.e. the method invoked depends on the parameter types as
> well as the declaring class, and there can be more than one method
> with the same name but with different parameter types in any class.

Multiple dispatching != Overloading

Java does not do multiple dispatch. It does method overload in a nice
way and it make it easier to dispatch on the 'right' method using the
'instanceof' check.

> Java of course uses message passing, but multiple dispatch and
> message passing are not mutually exclusive.

The are not. But Java (and C++) do "message passing" with signature
overload.

> If anyone insists otherwise, I will check it again as it seems
> to be as widespread a belief among non-Java programmers as "Lisp
> is an interpreted language" is among non-Lisp programmers.

Believe me. By now I am as much of a Java programmer as a (Common) Lisp
one. It is not a 'belief'. It is a fact.

Cheers

--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa

Marco Antoniotti

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to

Donald Fisk <donal...@inthan.be> writes:

> > The > method invoked can depend on the other arguments but these
> determine which > method is invoked at compile-time.

> Looks like we're using different definitions of multiple dispatch
> from each other. What I mean is that a.foo(b, c) and a.foo(d, e)
> can call different methods, both called foo and both belonging to
> the class of a, provided b and d belong to different classes or c
> and e belong to different classes. It may well be that the classes
> need to be known to the compiler -- I'll check this.

The discriminating feature between multiple dispatch and single
dispatch avec overloading is what you do with "regular" arguments (in
your example 'b', 'c', 'd', and 'e')..

Suppose you have the following class hierarchies

A O
|\ |
B C P

and a class O with a method called foo (using Java or C++ idioms)
which takes an argument, and overload it.
I.e.
class O {
foo(A x);
foo(B x);
foo(C x);
}

class P {
foo(B x);
}

Now suppose you have a B and a C instance which can both be stored in
a variable named 'bar', like in the following fragment

O oi = new O();
P pi = new P();
B bi = new B();
C ci = new C();
A bar = randomly_choose(bi, ci);

where 'randomly_choose' does the obvious thing. It signature is

A randomly_choose(B b, C c);

Now you want to call the 'right' method 'foo'. If you do

oi.foo(bar)
pi.foo(bar)

in Java and C++ the method that gets called is 'O::foo(A x)' in both
cases (please forgive me the mix of notations), indipendently of the
'true' class of the object contained in 'bar'. I.e., you must
explicitely cast the type of bar to get the 'right' method. In Java
this is tipically done by nesting a bunch of 'ifs' testing the second
argument with 'instanceof'. I.e. you would have to write

if (bar instanceof B) {
oi.foo((B) bar)
pi.foo((B) bar)
} else if (bar instanceof C) {
oi.foo((C) bar)
pi.foo((C) bar)
} else {
oi.foo(bar)
pi.foo(bar)
}

Suppose for a moment that 'bar' contained a reference to 'bi'. In
Common Lisp you could rewrite the calls to foo as

(foo oi bar) ; case [1]
(foo pi bar) ; case [2]

Now, in [1] the method that actually gets called correctly at runtime
without extra castings is O::foo(B x), while in [2] is P::foo(B x).

I.e. CLOS multiple dispatch does 'the right thing' at runtime with
minimum programmer's typing. On top of that, the Java (and C++) code
is brittle. You add a new class and you must change it.

Of course, there is always somebody (not you) who comes around and
says: oh yeah, I can do that in C++ with template tricks and so on.
The answer is: what happens when you want to dispatch on three
arguments? :)

Cheers

PS. I have the full examples in Java and Common Lisp.

Marco Antoniotti

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to

Marco Antoniotti <mar...@parades.rm.cnr.it> writes:

> Now suppose you have a B and a C instance which can both be stored in
> a variable named 'bar', like in the following fragment
>
> O oi = new O();
> P pi = new P();
> B bi = new B();
> C ci = new C();
> A bar = randomly_choose(bi, ci);
>
> where 'randomly_choose' does the obvious thing. It signature is
>
> A randomly_choose(B b, C c);
>
> Now you want to call the 'right' method 'foo'. If you do
>
> oi.foo(bar)
> pi.foo(bar)

Just for completeness. Java (and C++ with 'virtual' member functions)
do the right thing for single dispatch given the following definition

O pi = new P();

(Of course not in the above example, I just felt like adding this for
completeness).

Cheers

Jason Trenouth

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to

>>>>>>>>>>>>>>>>>> Original Message <<<<<<<<<<<<<<<<<<

On 08-11-99, 5:17:39 PM, Donald Fisk <donal...@inthan.be> wrote
regarding Re: Multiple dispatch in CLOS:

> > Unfortunately, for Java programmers, the non-Java programmers are
right. Java
> > dynamically dispatches only on the runtime type of the first argument.

> By "first argument" do you mean the object the message is sent to, or
> the first parameter?

The object the message is sent to.

> > The
> > method invoked can depend on the other arguments but these determine
which
> > method is invoked at compile-time.

...


> It may well be that the classes need to be known to the compiler --
I'll
> check this.

That's right, the other parameters need to be known to the compiler.
That's called "overloading" by the C++ and Java communities.
Multi-argument dispatch is normally taken to mean that runtime type
information for all the arguments is used decide which method to call.
If you're trying to use the term for what Java does then you're using
unorthodox terminology.

__Jason


Tim Bradshaw

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to
* Donald Fisk wrote:

> Looks like we're using different definitions of multiple dispatch
> from each other. What I mean is that a.foo(b, c) and a.foo(d, e)
> can call different methods, both called foo and both belonging to
> the class of a, provided b and d belong to different classes or c

> and e belong to different classes. It may well be that the classes


> need to be known to the compiler -- I'll check this.

*Only* if the types are *declared* differently at the point of call.
There is proper runtime dispatch only for the object the message is
sent to.

--tim

Robert Monfera

unread,
Nov 10, 1999, 3:00:00 AM11/10/99
to
Marco Antoniotti wrote:

>
> Donald Fisk <donal...@inthan.be> writes:
>
> > Java of course uses message passing, but multiple dispatch and
> > message passing are not mutually exclusive.

Correct. Message passing is but a subset of multiple dispatch, so they
_can't_ be mutually exclusive!

Regards
Robert

0 new messages