Multiple Dispatch Now, Please!

by chromatic

If you've never used multiple dispatch, you're in for a treat. We've had it working in Parrot for years, but Jonathan Worthington just added the basics of MMD support to Rakudo (Rakudo is an implementation of Perl 6).

Why do you want multiple dispatch? Here's a clever little example:

class Thing             {}
class Rock     is Thing {}
class Paper    is Thing {}
class Scissors is Thing {}

multi sub defeats(Thing    $t1, Thing    $t2) { 0 };
multi sub defeats(Paper    $t1, Rock     $t2) { 1 };
multi sub defeats(Rock     $t1, Scissors $t2) { 1 };
multi sub defeats(Scissors $t1, Paper    $t2) { 1 };

my $paper = Paper.new;
my $rock  = Rock.new;

say defeats($paper, $rock);
say defeats($rock, $paper);

Download the new Parrot release next Tuesday, 15 April 2008, then type:

$ perl Configure.pl
$ make
$ make perl6

... and you too can play with this in your own code.

Update: Note that multiple dispatch is different from static signature-based overloading and pattern matching in that multiple dispatch works correctly even when you don't know the specific types of the invocants at compile time. Imagine that I threw a rand() call in there, for example.


12 Comments

jason
2008-04-10 06:56:24
Is multiple dispatch really nothing more than function overloading? C++ response to this on my blog.
Michael Peters
2008-04-10 08:42:15
No, it's slightly different than function overloading in C++:
http://en.wikipedia.org/wiki/Multiple_dispatch
jason
2008-04-10 10:26:06
Thanks, I do see the difference now. I managed to throw together an example of how one might do runtime dispatch in C++.
Justin
2008-04-10 12:35:08
Looks like pattern matching in a functional language. Haskell version:


data Thing = Rock | Paper | Scissors


defeats Paper Rock = True
defeats Rock Scissors = True
defeats Scissors Paper = True
defeats _ _ = False -- wild card case


main = putStrLn ("Rock defeats paper " ++ show (defeats Rock Paper))

chromatic
2008-04-10 12:47:34
It's like pattern matching in some ways; I thought about mentioning that when I wrote the post, but I also thought that it would be more obvious that dispatch is dynamic, not static. Imagine that the objects get created randomly or due to user input or somehow in a way that is not statically resolvable.
vtp
2008-04-11 13:10:06
I think multiple dispatch is just like function overloading. But since Perl's typing is dynamic, it must be done at run time, instead of at compile time as in function overloading in C++.


The difference is only apparent if there is something in Perl 6 like polymorphism in C++.

Vince
2008-04-12 06:25:03
Perl 6 feels more like Java to me every day.
Ovid
2008-04-13 00:48:15
@vince: I'm not sure if the "feels more like Java" is a complaint, praise, or something in between. For those who might view a Java comparison as a complaint, it's worth noting that there are a lot of good things about Java and its method resolution is far superior to Perl 5's.
Ovid
2008-04-13 00:54:07
@vince: I should also point out that Java is single dispatch, not multiple dispatch. It determines method resolution at compile time, not runtime. As a result, you have to fall back to the visitor pattern, ugly if/else blocks or other tricks if you need to determine method resolution at runtime. With multiple dispatch, such "grunt work" goes away. Of course, Java does have an efficiency win with this, but it seems a huge price to pay for all of the buggy scaffolding people write to work around this.
jczeus
2008-04-16 07:21:31
Running the example above with Rakudo on parrot 0.6.1 results in a segfault on my machine


I reduced the example to this:


class Paper {}
my $paper = Paper.new


and got:


get_bool() not implemented in class 'Paper'
current instr.: 'parrot;PCT::HLLCompiler;command_line' pc 1290 (src/PCT/HLLCompiler.pir:688)
called from Sub 'parrot;Perl6::Compiler;main' pc 8860 (perl6.pir:183)

Tim Bunce
2008-04-16 07:41:25
Just after reading this I stumbled upon http://msdn2.microsoft.com/en-us/magazine/cc500572.aspx
It's an interview with Bjarne Stroustrup on the Evolution of Languages.


"The resulting code for multiple dispatch use-cases is shorter, simpler, uses less memory, and runs faster than all workarounds we have seen."


Lots of interesting nuggets in there.

Pm
2008-04-16 12:58:51
Some recent versions of Parrot seem to be having trouble with the 'perl6' executable on this script. We're looking into it, but in the meantime note that using "./parrot perl6.pbc" should still work.