Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ACCEPTS vs smartmatch in Hashes: what's the difference?

Tags:

raku

Theoretically, ~~ is syntactic sugar for ACCEPTS so the last two lines should return the same value:

my %myth-objects =  %(Þor => "Mjólnir", Oðinn => "Hugin") ;
say %myth-objects;
say %myth-objects.ACCEPTS("Oðinn");
say %myth-objects ~~ "Oðinn";

However, the first returns True and the second returns False. What am I missing here?

like image 267
jjmerelo Avatar asked Apr 02 '19 18:04

jjmerelo


2 Answers

There are two problems with what you have.

  1. Smartmatch has two execution layers.

    one is immediate

    'abc' ~~ $_ eq 'XYZ'
    

    .ACCEPTS is then called on the result, with the given value as the argument

    do given 'abc' { ($_ eq 'XYZ').ACCEPTS($_) }
    #                 ^                    ^
    #                 |                    |
    #                 +------- 'abc'-------+
    

    In the above case $_ eq 'XYZ' is False, and False.ACCEPTS(|) always returns False.
    (Similarly True.ACCEPTS(|) always returns True.)

    You could also return a Callable.

    'abc' ~~ * eq 'XYZ'
    

    This will appear to have the effect of removing the first immediate layer.
    (It doesn't actually do that though.)

    do given 'abc' { (* eq 'XYZ').ACCEPTS($_) }
    do given 'abc' { (* eq 'XYZ').($_) }
    do given 'abc' { $_ eq 'XYZ' }
    

    Or it could return a type or literal.

    'abc' ~~ ( 1 ?? Str !! Int ) # 'abc' ~~ Str
    do given 'abc' { ( 1 ?? Str !! Int ).ACCEPTS($_) }
    do given 'abc' { (      Str        ).ACCEPTS($_) }
                            Str         .ACCEPTS('abc')
    
  2. You have the left hand side, and the right hand side swapped.

    These two lines are similar.
    (Ignoring that there are really two execution layers.)

    'abc' ~~ 'XYZ'
    'XYZ'.ACCEPTS('abc')
    

    The important point to remember is that the right side of ~~ gets to decide how the smartmatch happens. The only way that can happen is if the method call was on it, not the left side.

(Note that all of the above also applies to when and where clauses. because they are also smartmatch features.)


So of course these have different results.

%myth-objects.ACCEPTS("Oðinn")
%myth-objects ~~ "Oðinn"

These three are similar.

         %myth-objects ~~ "Oðinn"
do given %myth-objects {  "Oðinn".ACCEPTS($_) }          # identical
                          "Oðinn".ACCEPTS(%myth-objects) # simplified

As are these

                    %myth-objects.ACCEPTS("Oðinn")
do given "Oðinn" {  %myth-objects.ACCEPTS($_) }    # expanded to two layers
         "Oðinn" ~~ %myth-objects                  # smartmatched
like image 177
Brad Gilbert Avatar answered Jan 02 '23 21:01

Brad Gilbert


Is it not the other way:

say 'Oðinn' ~~ %myth-objects;

According to the doc: The smartmatch operator aliases the left-hand side to $_ , then evaluates the right-hand side and calls .ACCEPTS($_) on it.

like image 37
LuVa Avatar answered Jan 02 '23 20:01

LuVa