Search code examples
matchrakuseqstringification

What does Any.match do?


It has the deceivingly simple code:

 method match(Any:U: |) { self.Str; nqp::getlexcaller('$/') = Nil }

However, this is the behavior it has:

(^3).match(1) # OUTPUT: «「1」␤»

So far, so good.

say (1,3 ... * ).match(77); # OUTPUT: «Nil␤»

Ooookey. What's happenning now?

say (1,3 ... * ).match(1);    # OUTPUT: «Nil␤»
say (1,3 ... * ).match(/\d/); # OUTPUT: «Nil␤»

Does not like sequences.

say (^10).match(/\d/); # OUTPUT: «「0」␤»

OK, makes sense again.

say <a b c>.match(/\w/); # OUTPUT: «「a」␤»

Back to normal. So is it that it does not like Seqs? I assume, because I've looked at the other classes' code and match is not reimplemented, all of them are calling that code. But I fail to see how returning a string and setting a variable from NPQ does that, or why it does not work on sequences.


Solution

  • .match is a search for a needle in a single haystack string. An infinite sequence stringifies to '...'.

    say (1,3 ... 9).Str;        # 1 3 5 7 9
    say (1,3 ... 9).match: '1'; # 「1」
    
    say (1,3 ... *).Str;        # ...
    say (1,3 ... *).match: '.'; # 「.」
    

    How I worked this out

    First, you're looking at the wrong method definition:

    method match(Any:U: |) { ... }
    

    Any:U is kinda like Any $ where not .defined except if it matched you would get the error message "Parameter '<anon>' of routine 'match' must be a type object of type 'Any', not an object instance ...".

    But you're passing a defined Seq. So your .match calls don't dispatch to the method definition you're looking at.

    To find out what a method dispatches to, use:

    say (1,3 ... *).^lookup('match').package ; # (Cool)
    

    A defined Seq will thus dispatch to the Cool code:

    method match(Cool:D: |c) {
        ...
        self.Stringy.match(|c)
    }
    

    So, next:

    say (1,3 ... *).^lookup('Stringy').package ; # (Mu)
    

    And the code:

    multi method Stringy(Mu:D $:) { self.Str }
    

    So check:

    say (1,3 ... *).Str; # ...
    

    Bingo.

    And confirm:

    say (1,3 ... *).match: '.'; # 「.」