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