Perl6 интерполирует массив в соответствии для функций И, ИЛИ, НЕ

Я пытаюсь заново выполнить мою программу для сопоставления всех, сопоставления с любым, сопоставления ни с одним из элементов в массиве. Некоторые из документации по Perl6 не объясняют поведение текущей реализации (Rakudo 2018.04), и у меня есть еще несколько вопросов.

(1) В документации по регулярному выражению сказано, что интерполяция массива в регулярное выражение совпадения означает "самое длинное совпадение"; однако этот код, похоже, не делает этого:

> my $a="123 ab 4567 cde";
123 ab 4567 cde
> my @b=<23 b cd 567>;
[23 b cd 567]
> say (||@b).WHAT
(Slip)
> say $a ~~ m/ @b /
 「23」    # <=== I expected the match to be "567" (@b[3] matching $a) which is longer than "23";

(2) (|| @b) - скольжение; Как я могу легко сделать ИЛИ или И всех элементов в массиве без явного цикла по массиву?

> say $a ~~ m:g/ @b /
(「23」 「b」 「567」 「cd」)
> say $a ~~ m:g/ ||@b /
(「23」 「b」 「567」 「cd」)
> say $a ~~ m/ ||@b /
 「23」
> say $a ~~ m:g/ |@b /
(「23」 「b」 「567」 「cd」)
> say $a ~~ m:g/ &@b /
(「23」 「b」 「567」 「cd」)
> say $a ~~ m/ &@b /
 「23」
> say $a ~~ m/ &&@b /
 「23」    # <=== && and & don't do the AND function

(3) То, что я закончил, - это сжатие моих предыдущих кодов в 2 строки:

my $choose = &any; # can prompt for choice of any, one, all, none here;
say so (gather { for @b -> $z { take $a ~~ m/ { say "==>$_ -->$z"; } <{$z}> /; } }).$choose;

вывод "True", как и ожидалось. Но я надеюсь, что более простой путь, без цикла "собери-возьми" и "за".

Большое спасибо за любые идеи.

lisprog

2 ответа

Решение

интерполировать массив в соответствии для функций AND, OR, NOT

Я не знаю лучшего решения, чем Мориц для AND,

Я покрываю OR ниже.

Один естественный способ написать NOT из списка токенов совпадения можно было бы использовать отрицательные версии предпросмотра или утверждения с задним взглядом, например:

my $a="123 ab 4567 cde";
my @b=<23 b cd 567>;
say $_>>.pos given $a ~~ m:g/ <!before @b> /;

дисплеи:

(0 2 3 4 6 7 9 10 11 13 14 15)

что позиции 12 матчей не 23, b, cd, или же 567 в строке "123 ab 4567 cde"показано линией ^s ниже которого указывают на каждую из соответствующих позиций символов:

my $a="123 ab 4567 cde";
       ^ ^^^ ^^ ^^^ ^^^
       0123456789012345

Я пытаюсь заново выполнить мою программу для сопоставления всех, сопоставления с любым, сопоставления ни с одним из элементов в массиве.

Эти звуковые соединения, как и некоторые другие вопросы, явно касаются соединений. Если вы подключились к своей существующей программе, мне / другим будет легче увидеть, что вы пытаетесь сделать.

(1)

||@b соответствует крайнему левому совпадающему токену в @bне самый длинный.

Написать |@bс одним |, чтобы найти самый длинный соответствующий токен в @b, Или, еще лучше, просто напишите @b, что является сокращением для того же самого.

Оба из этих образцов соответствия (|@b или же ||@b), как и любые другие шаблоны сопоставления, зависят от того, как работает механизм регулярных выражений, как кратко описано Морицем и более подробно ниже.

Когда механизм регулярных выражений сопоставляет регулярное выражение с входной строкой, он запускается в начале регулярного выражения и в начале входной строки.

Если он не совпадает, он проходит мимо первого символа во входной строке, отказываясь от этого символа, и вместо этого делает вид, что входная строка началась со второго символа. Затем он снова пытается сопоставить, начиная с начала регулярного выражения, но второй символ входной строки. Это повторяется до тех пор, пока не достигнет конца строки или не найдет совпадение.

Учитывая ваш пример, двигатель не соответствует прямо в начале 123 ab 4567 cde но успешно совпадает 23 начиная со второй позиции символа. Итак, это сделано - и 567 в вашем матче шаблон не имеет значения.

Один из способов получить ожидаемый ответ:

my $a="123 ab 4567 cde";
my @b=<23 b cd 567>;

my $longest-overall = '';
sub update-longest-overall ($latest) {
  if $latest.chars > $longest-overall.chars {
    $longest-overall = $latest
  }
}

$a ~~ m:g/ @b { update-longest-overall( $/ ) } /;

say $longest-overall;

дисплеи:

「567」

Использование :g объясняется ниже.

(2)

|@b или же ||@b в основном коде означают что-то совершенно не связанное с тем, что они означают внутри регулярного выражения. Как вы видете, |@b такой же как @b.Slip, ||@b средства @b.Slip.Slip который оценивает @b.Slip,

Чтобы сделать "параллельные" Longest-Match-Pattern-Wins OR из элементов @b, записывать @b (или же |@b) внутри регулярного выражения

Чтобы сделать "последовательный" крайний левый-матч-шаблон-побед OR из элементов @b, записывать ||@b внутри регулярного выражения

Я до сих пор не мог понять, что & а также && делать, когда используется для префикса массива в регулярном выражении. Мне кажется, что есть несколько ошибок, связанных с их использованием.

В некотором коде в вашем вопросе вы указали :g наречие. Это заставляет движок не останавливаться, когда он находит совпадение, а просто проходить мимо подстроки, с которой он только что совпал, и начинать попытки снова сопоставить дальше во входной строке.

(Есть и другие наречия. :ex наречие самое экстремальное. В этом случае, когда в заданной позиции во входной строке есть совпадение, движок пытается сопоставить любой другой шаблон совпадения в той же позиции в регулярном выражении и входной строке. Он продолжает делать это независимо от того, сколько совпадений он накопил, пока не попробует каждое последнее возможное совпадение в этой позиции в регулярном выражении и входной строке. Только когда все эти возможности исчерпаны, он перемещается на один символ вперед во входной строке и пытается исчерпывающе сопоставить все заново.)

(3)

Мой лучший снимок:

my $a="123 ab 4567 cde";
my @b=<23 b cd 567>;
my &choose = &any;
say so choose do for @b -> $z {
  $a ~~ / { say "==>$a -->$z"; } $z /
}

(1) В документации по регулярному выражению сказано, что интерполяция массива в регулярное выражение совпадения означает "самое длинное совпадение"; однако этот код, похоже, не делает этого:

Фактическое правило состоит в том, что регулярное выражение находит крайнее левое совпадение первым, а самое длинное совпадение - вторым.

Тем не менее, крайнее левое правило верно для всех совпадений регулярных выражений, поэтому в документации регулярных выражений не упоминается об этом явно, когда речь идет об альтернативах.

(2) (|| @b) - скольжение; Как я могу легко сделать ИЛИ или И всех элементов в массиве без явного цикла по массиву?

Вы всегда можете сначала создать регулярное выражение в виде текста:

my $re_text = join '&&', @branches;
my $regex   = re/ <$re_text> /;
Другие вопросы по тегам