On Sat, Sep 25, 2021 at 2:30 PM Joseph Brenner <doom...@gmail.com> 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 <b2gi...@gmail.com> 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 <doom...@gmail.com> 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 Hero of 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. > >> > > >