Подпись Раку (массив @r) не является (массивом: D)?

Кажется, я не могу разобраться в этом сообщении об ошибке Raku, которое я нашел при изучении грамматики...


Cannot resolve caller report(Array:D); none of these signatures matches:
(Array @r)
(Match $r)

Так массив не является массивом?! Как это работает и как узнать, почему? Вот полная программа и вывод.

#!/usr/bin/env perl6
use v6;
grammar Integers {
    rule TOP      { ^ .*? <targets> .* $  }
    rule targets  { <integer>+ % ',' }
    token integer { \d+ }
}

multi sub report(Array @r) { say @r.raku }
multi sub report(Match $r) { say $r.raku }

sub MAIN() {
    my $result = Integers.parse(' a 1234 ');
    report($result);
    report(%$result{'targets'});
    report(%$result{'targets'}{'integer'});
}
#`( output:
Match.new(:orig(" a 1234 "), :from(0), :pos(8), :hash(Map.new((:targets(Match.new(:orig(" a 1234 "), :from(3), :pos(8), :hash(Map.new((:integer([Match.new(:orig(" a 1234 "), :from(3), :pos(7))]))))))))))
Match.new(:orig(" a 1234 "), :from(3), :pos(8), :hash(Map.new((:integer([Match.new(:orig(" a 1234 "), :from(3), :pos(7))])))))
Cannot resolve caller report(Array:D); none of these signatures matches:
    (Array @r)
    (Match $r)
  in sub MAIN at /home/hans/Programming/Raku/Parsing/Array_Array.raku line 16
  in block <unit> at /home/hans/Programming/Raku/Parsing/Array_Array.raku line 3
)
Принципы ООП в JavaScript
Принципы ООП в JavaScript
Парадигма объектно-ориентированного программирования имеет 4 основных принципа,
8
0
105
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ну, у меня есть частичный ответ на мой собственный вопрос. Если я изменю (Array @r) на (Array $r) или если просто отброшу Array и использую (@r).

Согласно docs.raku.org «Если пользователь не указал тип, Raku предполагает, что тип — Any». Это объясняет, почему (@r) работает. Это просто (любой @r)... я думаю.

Что касается того, почему (Array:D) должен быть закодирован как (Array $r), я все еще пытаюсь понять это. Все любопытнее и любопытнее.

Вы можете закодировать это как Array:D $r, если хотите. Более общий Array $r также будет работать, но он более общий — он будет принимать Array, даже если это просто объект типа Array, а не экземпляр.

raiph 23.01.2023 23:37
Ответ принят как подходящий

Вы, кажется, смущены функциональностью сигилов и набора текста.

Когда вы используете сигил @, вы подразумеваете Позиционное ограничение.

sub foo(@a) { ... }

возьмет все, что выполняет роль Positional.

foo( @b );
foo( [1,2,3] );
foo( (1,2,3) );

Когда вы указываете тип с @ в подписи, вы указываете, что вам нужен Positional, который принимает только этот тип в качестве своих элементов. Теперь, как параметр подпрограммы, это сильно ограничивает то, что вы можете указать, поскольку [1,2,3] — это не массив с ограничением на Int, это массив, который оказывается заполненным только значениями Int.

Теперь вернемся к вашему примеру: что означает (Array @r)? Это означает, что вам нужен Positional, который ограничивает Array объекты. Проще говоря: вам нужен массив, который должен состоять из массивов в качестве своих элементов.

Я не думаю, что это то, что вы имели в виду?

Теперь, почему (Array $r) работает? Потому что это указывает на то, что вам нужен объект, который является Array в качестве параметра. Это также ограничивает то, что вы хотите, потому что тогда это должно быть Array, а не List, например.

sub foo(Array $r) { ... }
foo(@a);         # works
foo( [1,2,3] );  # works
foo( (1,2,3) );  # does *not* work

Наконец, я думаю, вы захотите использовать встроенную функцию dd вместо создания собственной функции report.

Итак, (Array @r) можно описать как массив массивов r или как массив Positionals r? Что касается того, почему я повторно реализую dd, то как я изучаю синтаксис для доступа к свойствам объекта Match.

FyFAIR 25.01.2023 23:05
Positional @r будет массивом Positionals, поэтому Array @r действительно является массивом Arrays. :-)
Elizabeth Mattijsen 26.01.2023 10:59

Привет @FyFAIR и добро пожаловать в раку. IMO raku — отличный инструмент, но у него мало ограничений. Так что, пожалуйста, наберитесь терпения, так как когда он щелкнет, оно того стоит ;-)

Я взял на себя смелость переформулировать ваш пример так, как я бы это сделал:

grammar Integers {
    token TOP      { ^ .*? <targets> .* $  }
    token targets  { <integer>+ % ',' }
    token integer { \d+ }
}

sub MAIN() {
    my $result = Integers.parse(' a 1234 '); 
    dd $result;
    dd $result<targets>;
    dd $result<targets><integer>;    #<== a list of matches with one element
    dd $result<targets><integer>[0];
    say "$result<targets><integer>[0]";
}

Integers $result = Match.new(:orig(" a 1234 "), :from(0), :pos(8), :hash(Map.new((:targets(Match.new(:orig(" a 1234 "), :from(3), :pos(7), :hash(Map.new((:integer([Match.new(:orig(" a 1234 "), :from(3), :pos(7))]))))))))))
Match.new(:orig(" a 1234 "), :from(3), :pos(7), :hash(Map.new((:integer([Match.new(:orig(" a 1234 "), :from(3), :pos(7))])))))
[Match.new(:orig(" a 1234 "), :from(3), :pos(7))]
Match.new(:orig(" a 1234 "), :from(3), :pos(7))
1234

Итак... вот мои замечания:

  • Вы очень близки (!)
  • Рекомендации @lizmat по dd сослужили мне хорошую службу
  • используйте @ в качестве символа для @lists, если вы не хотите сюрприза
  • просто используйте token, если вам действительно не нужно rule
  • типы отлично подходят для проверок и множественных операций... Сначала я получаю функциональный код без типов, а затем постепенно добавляю их, чтобы я мог видеть, выполняют ли они свою работу.
  • Int @array означает, что захват будет проверять, например. my Int @array = [1,2,3] который (как говорит lizmat) не совпадает с массивом со значениями Int [1,2,3] (здесь проверка типа делегирует контроль над тем, что присваивается массиву)
  • нет необходимости в derefs в стиле Perl, таких как %$
  • <key> то же самое, что и {'key'}, но меньше печатать
  • объект Match очень сложный и мощный... dd показывает внутренности, но обычно это перебор
  • используйте say и уточните Match с помощью "" (или .Str), чтобы получить то, что вам действительно нужно
  • use Grammar::Tracer; ты друг

Спасибо за переписку и замечания, особенно Grammar:Tracer.

FyFAIR 25.01.2023 23:12

Другие вопросы по теме