Perl6 интерполирует массив в соответствии для функций И, ИЛИ, НЕ - PullRequest
0 голосов
/ 13 июня 2018

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

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

> 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) - скольжение;как мне легко выполнить OR или AND для всех элементов в массиве без явного зацикливания в массиве?

> 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 ]

0 голосов
/ 13 июня 2018

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

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

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

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

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 inстрока "123 ab 4567 cde", показанная линией ^ s ниже, которая указывает на каждую из совпадающих позиций символов:

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

Я пытаюсь заново выполнить свою программу для соответствия-all, match-any, match-none элементов массива.

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

(1)

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

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

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

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

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

В вашем примере двигатель не может соответствовать прямо в начале 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.

Чтобы сделать "параллельное" самое длинное совпадение с шаблоном побед OR элементов @b, напишите @b (или|@b) внутри регулярного выражения .

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

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

В некотором коде в вашем вопросе вы указали наречие :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 /
}
0 голосов
/ 13 июня 2018

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

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

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

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

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

my $re_text = join '&&', @branches;
my $regex   = re/ <$re_text> /;
...