in reply to The beauty of MMD
in thread Perl 5's greatest limitation is...?

First of all, as was already pointed out, I am not arguing that multi-methods are necessarily bad. Just that you have not convinced me. I further went on to say what would be required to convince me. The fact that this argument can be used by someone else with regards to something that I am convinced is good is not a refutation of that form of argument. No number of examples of people with mistaken opinions will convince me that it is a bad idea for people to try to form their own opinions. In fact no number of examples where I have had a mistaken opinion will convince me that I shouldn't try to have my own opinions!

Now I see what you're saying in your example, but I have several major caveats.

First of all let's separate the need for a dispatch mechanism from the desire for multi-method dispatch. Much of what you've just said for multi-method dispatch by type works perfectly well already in Perl if you're dispatching by class using OO. Arguing for how great multi-method dispatch would be using examples where OO dispatch suffices is not going to convince me. You don't need to convince me that there is a need for built-in dispatch mechanisms. You need to convince me that there is a need for complex built-in dispatch mechanisms.

Remember that I already suspect that a basic maintainance problem with heavily factored OO code is that there is an implicit if in every method call, making the complexity of OO code higher than procedural code of similar length. I am concerned that making the dispatch potentially more complex makes the complexity higher still. In particular I had this concern from descriptions of Perl 6 has had rules to try to figure out a type if nothing matches exactly. When I read descriptions of how it does that, I'm often left wondering how often it would wind up dispatching somewhere I don't want it to dispatch, and how often I would want an error but wouldn't get one.

Now you used one example where it seems to make sense to dispatch based on number of arguments. And that is an accessor which plays setter and getter. However I have another solution to that problem which I like a lot. And that solution is name your setters and getters differently! A really cute idiom for this in Ruby does like this. If you name your getter bar, then you name your setter bar=. Then Ruby has a nice piece of syntactic sugar where you can write foo.bar = baz; and it automatically knows to call your bar= method. (Ruby has another nice piece of syntactic sugar where it will autogenerate acceptable default accessors for you very easily, but I digress.)

There is a basic choice here. You can either try to have a complex dispatch method to allow you to overload a method with many different meanings. Or you can have a straightforward dispatch method and have a number of similar (but very distinct!) methods. My natural inclination is towards the latter. (This would be one of the reasons that I am not a fan of multiple inheritance...)

Now lets move on to hand-rolled dispatch mechanisms. As I've already noted, Perl has a working OO dispatch mechanism. Therefore if I write a hand-rolled dispatch mechanism, my needs are likely to be rather customized. For one thing I'm almost always dispatching on value. Secondly I sometimes have a customized dispatch table - you can pass the dispatch table into the function. Thirdly I frequently want to customize the "fallback" behaviour. Fourth I usually have a non-trivial lookup to figure out what I'm dispatching on.

Now I see how a smart MMD system could satisfy some of those needs. But I don't think (I may be mistaken, of course) that proposals for Perl 6's MMD system would be flexible enough to handle the cases where I want to write a customized dispatch system in Perl 5.

Now let's wrap up loose ends.

The optimization note doesn't matter to me. Perl is simply not a bottleneck for the kinds of things that I want to do with it. (Usually the bottleneck is the database.) And if I really wanted performance, Perl wouldn't be the tool that I'd reach for. That isn't about to change any time soon.

Please don't take any of what I've said as a slam on Perl 6. My understanding of Perl 6 says that I can ignore whatever I want to ignore. I'm fine with not using a capacity for MMD.

And about the PS, I'm not only hoping to exchange a beer or three, I'm hoping that you have some good ideas on where to find the best parties. :-)

Replies are listed 'Best First'.
Re^2: The beauty of MMD
by Ovid (Cardinal) on Jul 28, 2005 at 22:59 UTC

    tilly wrote:

    Much of what you've just said for multi-method dispatch by type works perfectly well already in Perl if you're dispatching by class using OO. Arguing for how great multi-method dispatch would be using examples where OO dispatch suffices is not going to convince me.

    I'm not sure I follow you here. Are you suggesting that in examples like I provided, the invocants be in different classes? Whenever possible, I really like to minimize the number of classes and creating a new class just to handle a different argument type to a method frequently does not make sense. One example of this would be the constructor:

    my $parser1 = Some::Parser->new($string); my $parser2 = Some::Parser->new($uri_object); my $parser3 = Some::Parser->new($fh_object);

    In that example, with three constructors, each taking a different argument type, we can still return objects in the same class. Class-based dispatching wouldn't make sense there. Did I misunderstand what you were saying?

    Dan Sugalski points to event driven code where different objects generate events and your event handlers are a series of methods whose arguments are the objects generating the events. I shouldn't push the event handling into the objects themselves because they shouldn't care how they're going to be used. Instead, I have a simple GUI class which knows that it's supposed to handle events. This is a common Java idiom and it works very well.

    The main problem I have with MMD is I am frequently more interested in the interface an object provides rather than its type/class.

    Oh, and you'll see that I'm not the one who used the getter/setter example. While it's a reasonable example that fits well with many people's coding styles, I also prefer different names there because the methods are doing different things. When the methods are conceptually doing the same thing, they should have the same name, if possible.

    Update: Whoops! I guess I did use a getter/setter example :)

    Cheers,
    Ovid

    New address of my CGI Course.

      As for the invocants being in in different classes, that is indeed what I suggested. Like LWP does with the LWP::Protocol::* classes. This solution has pros and cons, with the need for appropriate classes to exist being one of the cons. But if we're going to rule out a design technique because it requires us to create a few extra classes, then we would never use MVC. Sometimes it is not worth adding classes, but if it makes sense, don't hesitate.

      Speaking of MVC, Dan Sugalski's prolems seems to me to be one that you can solve with an MVC design. In fact people happily do so in languages like Smalltalk and Ruby. Yes, it does mean designs with some extra redispatching. I don't consider that a major flaw.

      As for your Some::Parser example, I grant that a direct class-based dispatch doesn't work there. However it is trivial to extend it in ways where a direct MMD dispatch won't work either. For instance suppose that you're parsing any of several related formats and need custom logic to autodetect which format you've been presented with. If you're getting that specialized, it makes sense to me to have customized dispatch logic. Not every facility needs to be built into the language, and people have been writing parsers with customizable behaviour since before either of us started programming.

      I agree with you about interfaces being more important than types and classes. And that's one of the reasons that I have no problem writing small helper classes whose job is to do the translation so that different kinds of things can present the interface that you want.

      And I should point out that you did use the getter/setter example. I direct you to your implementation of name in The beauty of MMD.