Since nobody else has answered yet, I'll try to say something.
I'll post this also to perl6-language so that those who know better
can comment on this.

On 8/28/06, Mark Stosberg <[EMAIL PROTECTED]> wrote:
First, what's the recommended reference for learning how dispatching to
the right 'multi' sub is resolved. ?

http://dev.perl.org/perl6/doc/synopsis.html

S12 seems most relevant (e.g. the section "Multisubs and Multimethods")
S06 might also be relevant

I'd like to know the expected behavior in this case:

multi sub foo () { say "b: " }
multi sub foo () { say "a: " }
foo();

I would expect it would throw an error or at least a warning, since
there's no clear way to choose a correct sub to dispatch to.

IMHO this is either the case where you define same sub twice, which is
an error (and so foo() would never get called) according to S06:
<quote>
Redefining a stub subroutine does not produce an error, but redefining
an already-defined subroutine does. If you wish to redefine a defined
sub, you must explicitly use the "is instead" trait.
</quote>

or, if not that case, then this is defining two multi-subs which have
the same "long-name". According to S12 the later multi-sub will then
hide the earlier one, and foo() would then allways call the second
multi-sub, saying "a: "
<quote>
For subs or methods declared multi, only one instance of the long name
can be in any namespace, and it hides any outer (or less-derived)
routines with the same long name.
</quote>

Pugs currently dispatches to one anyway, without a warning.

If Pugs allways dispatches to the second one, then this might be the
right behaviour.

A more insidious version of the same case is the following, which
I accidentally wrote more than once already...and then wondered why
my code wasn't working as expected...

multi sub foo (%names?) { say "b: " }
multi sub foo (@pos?) { say "a: " }

There, I have distinct arguments, but they are both optional, making
them the same as the case above.

This isn't exactly the same as above. In this case the two multi-subs
just might have different "long-names" and so one would not hide the
another.

I'm not 100% sure about whether these have different "long-name" or
not as I don't know how exactly the "long-name" is created.

If I'm right that these do have different "long-name" then IMHO the
call to foo() would throw an exception because there's a tie between
two equally-good candidates for multi-dispatch and S12 says that in
such a case an exception is thrown:
<quote>
When you call a routine with a particular short name, if there are
multiple visible long names, they are all considered candidates. They
are sorted into an order according to how close the run-time types of
the arguments match up with the declared types of the parameters of
each candidate. The best candidate is called, unless there's a tie, in
which case the tied candidates are redispatched using any additional
tiebreaker long names (see below).

If a tie still results, only candidates marked with the default trait
are considered, and the best matching default routine is used. If
there are no default routines, or if the available defaults are also
tied, a final tie-breaking proto sub is called, if there is one (see
above). Otherwise an exception is thrown.
</quote>

--
Markus Laire

Reply via email to