ПРИНИМАЕТ против Smartmatch в Хешах: какая разница? - PullRequest
6 голосов
/ 02 апреля 2019

Теоретически, ~~ является синтаксическим сахаром для ACCEPTS, поэтому последние две строки должны возвращать одно и то же значение:

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

Однако первый возвращает True, а второй возвращает False. Что мне здесь не хватает?

Ответы [ 2 ]

7 голосов
/ 03 апреля 2019

Есть две проблемы с тем, что у вас есть.

  1. Smartmatch имеет два уровня исполнения.

    один немедленный

    'abc' ~~ $_ eq 'XYZ'
    

    .ACCEPTS затем вызывается для результата с заданным значением в качестве аргумента

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

    В приведенном выше случае $_ eq 'XYZ' равно False, а False.ACCEPTS(|) всегда возвращает False.
    (Аналогично True.ACCEPTS(|) всегда возвращает True.)

    Вы также можете вернуть Callable.

    'abc' ~~ * eq 'XYZ'
    

    Это будет иметь эффект удаления первого непосредственного слоя.
    (Хотя на самом деле это не так.)

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

    Или он может вернуть тип или литерал.

    'abc' ~~ ( 1 ?? Str !! Int ) # 'abc' ~~ Str
    do given 'abc' { ( 1 ?? Str !! Int ).ACCEPTS($_) }
    do given 'abc' { (      Str        ).ACCEPTS($_) }
                            Str         .ACCEPTS('abc')
    
  2. У вас есть левая сторона, а правая часть поменялась местами.

    Эти две строки похожи.
    (Игнорируя, что действительно есть два уровня выполнения.)

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

    Важно помнить, что правая сторона ~~ решает, как происходит smartmatch. Единственный способ, которым это может произойти, это если вызов метода был на нем, а не на левой стороне.

(Обратите внимание, что все вышеперечисленное также относится к предложениям when и where. Потому что они также являются функциями smartmatch.)


Так что, конечно, они имеют разные результаты.

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

Эти три схожи.

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

Как и эти

                    %myth-objects.ACCEPTS("Oðinn")
do given "Oðinn" {  %myth-objects.ACCEPTS($_) }    # expanded to two layers
         "Oðinn" ~~ %myth-objects                  # smartmatched
6 голосов
/ 02 апреля 2019

Разве нет другого пути:

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

Согласно документу: Оператор smartmatch присваивает левой части значение $ _, затем вычисляет правую часть и вызывает для нее .ACCEPTS ($ _).

...