On Monday, June 9, 2003, at 09:19 AM, Mark A. Biggar wrote:
On Mon, Jun 09, 2003 at 01:26:22PM +0100, Piers Cawley wrote:
      multi factorial (0) { 1 }
      multi factorial ($n) { $n * factorial($n - 1) }

That's a bad example, as it's really not MMD. It's a partially pre-memoized function instead.

It's MMD if you think of the number 0 as being a "subclass" of C<int> or C<num>. In other words, you have an C<num> class, and then a subclass of C<num> that binds the value to always be zero.


In a not-too-twisted fashion, you can think of any constant as being a "subclass" of its base type, overridden to store exactly one possible value. It's like instance-based (classless) inheritance, which we haven't discussed much, but which I hope we eventually get to, because it's bloody useful... Sigh...


Which brings up a issue. Is it really MMD if you're only dispatching on
a single invocant? Most of the examples I've seen for MMD so far use
only a single invocant and are really either regular dispatch or simple
overloading instead. MMD only becomes really interesting if you
have multiple invocants possibly with best-match signature matching
involved.

I think it's a matter of semantics: a single-invocant routine is still a "multi", and still semantically MMD, because it uses the same internal dispatcher as an N-invocant one, and checks the same list of possible variants. So you can have:


    multi bar (Baz $b :         ...);   # one invocant
    multi bar (Foo $f :         ...);   # one invocant, but different!
    multi bar (Foo $f, Baz $b : ...);   # two invocants

All three of those are multimethod variants of a routine named C<bar>. The MMD mechanism has to determine which of those three variants to use, based on the invocant(s) -- of which there may be one, or several, for any given call to C<bar>. Even if there only happens to be one invocant, it's still the same dispatcher, sifting through the same possible variants.


The single-invocant C<multi> thing I still find confusing at this point is that, for example, you can't actually have C<multi><method>s! That is, you can't do this:


    class Foo {
        method bar (int $i);
        method bar (str $s);                   # ERROR
        method bar (str $s1, str $s2);
    }

You'd have to do this:

    class Foo {
        multi bar (Foo $self, int $i : );      # semicolon optional
        multi bar (Foo $self, str $s : );
        multi bar (Foo $self, str $s1, str $s2 : );
    }

Which, internally, makes some sense -- they have to go to a more complicated dispatcher than normal methods -- but is semantically icky, IMO, and I hope/wish we could find a better way of expressing that. Perhaps E6 will help.

MikeL



Reply via email to