Кажется, я не могу разобраться в этом сообщении об ошибке 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
)
Ну, у меня есть частичный ответ на мой собственный вопрос. Если я изменю (Array @r) на (Array $r) или если просто отброшу Array и использую (@r).
Согласно docs.raku.org «Если пользователь не указал тип, Raku предполагает, что тип — Any». Это объясняет, почему (@r) работает. Это просто (любой @r)... я думаю.
Что касается того, почему (Array:D) должен быть закодирован как (Array $r), я все еще пытаюсь понять это. Все любопытнее и любопытнее.
Вы, кажется, смущены функциональностью сигилов и набора текста.
Когда вы используете сигил @
, вы подразумеваете Позиционное ограничение.
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 или как массив Positional
s r? Что касается того, почему я повторно реализую dd, то как я изучаю синтаксис для доступа к свойствам объекта Match.
Positional @r
будет массивом Positional
s, поэтому Array @r
действительно является массивом Array
s. :-)
Привет @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
Итак... вот мои замечания:
dd
сослужили мне хорошую службу@
в качестве символа для @lists, если вы не хотите сюрпризаtoken
, если вам действительно не нужно rule
Int @array
означает, что захват будет проверять, например. my Int @array = [1,2,3]
который (как говорит lizmat) не совпадает с массивом со значениями Int [1,2,3]
(здесь проверка типа делегирует контроль над тем, что присваивается массиву)%$
<key>
то же самое, что и {'key'}
, но меньше печататьsay
и уточните Match с помощью ""
(или .Str
), чтобы получить то, что вам действительно нужноuse Grammar::Tracer;
ты другСпасибо за переписку и замечания, особенно Grammar:Tracer
.
Вы можете закодировать это как
Array:D $r
, если хотите. Более общийArray $r
также будет работать, но он более общий — он будет приниматьArray
, даже если это просто объект типаArray
, а не экземпляр.