Re: Order of multi sub definitions can resolve dispatch ambiguity

2021-09-25 Thread Brad Gilbert
On Sat, Sep 25, 2021 at 2:30 PM Joseph Brenner  wrote:

> > Since subsets are just code it would be difficult to impossible
> > to determine all of the ones that can match without actually
> > running them all. This would slow down every call that uses
> > multiple subsets.
>
> I can see how there would be a big performance hit, but I haven't
> yet turned up any reference to this behavior in the docs.  I
> don't see anything to clue you in that subsets are an exception,
> and I don't think there's anything about
> order-of-definition-of-sub being a tie-breaker under any
> circumstances.
>

The docs are not the definitive source of truth.
They are at best an approximation.

> By most narrow candidate, it means by type.
>
> If you'd said that to me, I'd still have expected it to work the
> way that I did, because the way I look at it I'm creating new
> types via subset.
>

By type I mean something that can be instantiated or subclassed.
Subsets cannot do either of those two things.
You can create a subset of a subset, but that is not the same thing.


> > All subsets "of" the same type are sorted by the order they are
> > written.
>
> Even if I'd figured that two subsets of Str were going to treated as Str,
> I'd have expected an "Ambiguous call" error.
>
> If the two subsets are defined in different modules I suspect you
> could get some strange behavior that would be hard to debug.
> It's not always immediately obvious in what order two things were
> defined.
>

Doing what you want would make using subsets with multis much less useful.

multi factorial ( 0 --> 1 ){}
multi factorial ( 1 --> 1 ){}
multi factorial ( UInt \n ){ factorial(n - 1) * n }

say factorial( 1 );
# ERROR: both UInt and 1 subsets match.

You could modify the general case, but that is tedious and error prone.

multi factorial ( Int \n where {$_ >= 0 && $_ != 0 && $_ != 1} ){
factorial(n - 1) * n }

(The reason I didn't just do $_ >= 2 is that if another multi is added it
should be dealt with in the same way as 0 and 1)


> On 9/24/21, Brad Gilbert  wrote:
> > This is intended behavior.
> >
> > Since subsets are just code it would be difficult to impossible to
> > determine all of the ones that can match without actually running them
> all.
> > This would slow down every call that uses multiple subsets.
> >
> > By most narrow candidate, it means by type. All subsets "of" the same
> type
> > are sorted by the order they are written.
> >
> > The ambiguity it talks about is when two candidates have the same level
> of
> > type for a given input. For example Str and Int for an IntStr.
> >
> >
> > On Fri, Sep 24, 2021, 1:32 AM Joseph Brenner  wrote:
> >
> >> This code uses multi dispatch with constraints that are ambiguous
> >> in a few cases, because there's some overlap in the lists of
> >> monsters and heroes: 'mothera' and 'godzilla'.
> >>
> >> my @monsters = < godzilla  mothera ghidora  gammera  golem
> >> wormface >;
> >> my @heroes   = < beowulf   bluebeetle  bernie   mothera  godzilla
> >> maynard_g_krebs >;
> >>
> >> subset Monster of Str where { $_ eq any( @monsters ) };
> >> subset Heroof Str where { $_ eq any( @heroes ) };
> >>
> >> ## Monster is favored over Hero because of the order of definition
> >> of these multi subs
> >> multi sub speak (Monster $m) {
> >> say "The monster, $m roars!";
> >> }
> >> multi sub speak (Hero $h) {
> >> say "The hero, $h shouts!";
> >> }
> >>
> >> speak('ghidora');  # The monster, ghidora roars!
> >> speak('beowulf');  # The hero, beowulf shouts!
> >> speak('mothera');  # The monster, mothera roars!
> >>
> >> I would've expected that in the case of 'mothera', this would
> >> error out unless an "is default" was added to one of the multi
> >> subs.  Instead the ambiguity is resolved by the order of
> >> definition: if you reverse the order of the "multi sub speak"s,
> >> then mothera is treated as Hero not Monster.
> >>
> >> This is not the behavior described in the documentation:
> >>
> >>  https://docs.raku.org/language/glossary#index-entry-Multi-Dispatch
> >>  Multi-dispatch§
> >>
> >>  The process of picking a candidate for calling of a set of
> >>  methods or subs that come by the same name but with different
> >>  arguments. The most narrow candidate wins. In case of an
> >>  ambiguity, a routine with is default trait will be chosen if
> >>  one exists, otherwise an exception is thrown.
> >>
> >
>


Re: Order of multi sub definitions can resolve dispatch ambiguity

2021-09-25 Thread Joseph Brenner
> Since subsets are just code it would be difficult to impossible
> to determine all of the ones that can match without actually
> running them all. This would slow down every call that uses
> multiple subsets.

I can see how there would be a big performance hit, but I haven't
yet turned up any reference to this behavior in the docs.  I
don't see anything to clue you in that subsets are an exception,
and I don't think there's anything about
order-of-definition-of-sub being a tie-breaker under any
circumstances.

> By most narrow candidate, it means by type.

If you'd said that to me, I'd still have expected it to work the
way that I did, because the way I look at it I'm creating new
types via subset.

> All subsets "of" the same type are sorted by the order they are
> written.

Even if I'd figured that two subsets of Str were going to treated as Str,
I'd have expected an "Ambiguous call" error.

If the two subsets are defined in different modules I suspect you
could get some strange behavior that would be hard to debug.
It's not always immediately obvious in what order two things were
defined.


On 9/24/21, Brad Gilbert  wrote:
> This is intended behavior.
>
> Since subsets are just code it would be difficult to impossible to
> determine all of the ones that can match without actually running them all.
> This would slow down every call that uses multiple subsets.
>
> By most narrow candidate, it means by type. All subsets "of" the same type
> are sorted by the order they are written.
>
> The ambiguity it talks about is when two candidates have the same level of
> type for a given input. For example Str and Int for an IntStr.
>
>
> On Fri, Sep 24, 2021, 1:32 AM Joseph Brenner  wrote:
>
>> This code uses multi dispatch with constraints that are ambiguous
>> in a few cases, because there's some overlap in the lists of
>> monsters and heroes: 'mothera' and 'godzilla'.
>>
>> my @monsters = < godzilla  mothera ghidora  gammera  golem
>> wormface >;
>> my @heroes   = < beowulf   bluebeetle  bernie   mothera  godzilla
>> maynard_g_krebs >;
>>
>> subset Monster of Str where { $_ eq any( @monsters ) };
>> subset Heroof Str where { $_ eq any( @heroes ) };
>>
>> ## Monster is favored over Hero because of the order of definition
>> of these multi subs
>> multi sub speak (Monster $m) {
>> say "The monster, $m roars!";
>> }
>> multi sub speak (Hero $h) {
>> say "The hero, $h shouts!";
>> }
>>
>> speak('ghidora');  # The monster, ghidora roars!
>> speak('beowulf');  # The hero, beowulf shouts!
>> speak('mothera');  # The monster, mothera roars!
>>
>> I would've expected that in the case of 'mothera', this would
>> error out unless an "is default" was added to one of the multi
>> subs.  Instead the ambiguity is resolved by the order of
>> definition: if you reverse the order of the "multi sub speak"s,
>> then mothera is treated as Hero not Monster.
>>
>> This is not the behavior described in the documentation:
>>
>>  https://docs.raku.org/language/glossary#index-entry-Multi-Dispatch
>>  Multi-dispatch§
>>
>>  The process of picking a candidate for calling of a set of
>>  methods or subs that come by the same name but with different
>>  arguments. The most narrow candidate wins. In case of an
>>  ambiguity, a routine with is default trait will be chosen if
>>  one exists, otherwise an exception is thrown.
>>
>