perl6 插入数组以匹配 AND、OR、NOT 函数

perl6 interpolate array in match for AND, OR, NOT functions

我正在尝试重新执行我的程序以匹配数组中的项目的全部匹配、任意匹配、匹配none。 Perl6 上的一些文档没有解释当前实现 (Rakudo 2018.04) 的行为,我还有几个问题。

(1) 关于正则表达式的文档说将数组插值到匹配正则表达式中意味着 "longest match";然而,这段代码似乎并没有这样做:

> 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) 我最后做的是将我以前的代码压缩成两行:

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"。但我希望有一种更简单的方法,没有 "gather-take" 和 "for" 循环。

非常感谢您的任何见解。

lisprog

(1) Documentation on regex says that interpolating array into match regex means "longest match"; however, this code does not seem to do so:

实际规则是正则表达式首先找到最左边的匹配项,然后找到最长的匹配项。

但是,最左边的规则适用于所有正则表达式匹配项,这就是正则表达式文档在谈论交替时没有明确提及它的原因。

(2) (||@b) is a Slip; how do I easily do OR or AND of all the elements in the array without explicitly looping through the array?

您始终可以先将正则表达式构建为文本:

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

interpolate array in match for AND, OR, NOT functions

对于 AND,我不知道有什么比 Moritz 的更好的解决方案了。

我在下面覆盖OR

编写匹配标记列表的 NOT 的一种自然方法是使用 lookahead 或后向断言的否定版本,例如:

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)

not23bcd567的12个匹配的位置字符串 "123 ab 4567 cde",由下面的 ^s 行显示,它指向匹配的每个字符位置:

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

I am trying to re-do my program for match-all, match-any, match-none of the items in an array.

这些声音连接点和您的其他问题显然都是关于连接点的。如果您链接到现有程序,me/others 可能会更容易看到您正在尝试做什么。

(1)

||@b 匹配 @b 最左边的 匹配标记,而不是 最长的 匹配标记。

|@b,用单个 |,来匹配最长匹配的记号@b。或者,更好的是,只写普通的 @b,即 shorthand 同样的东西。

这两种匹配模式(|@b||@b)与任何其他匹配模式一样,受正则表达式引擎工作方式的影响,Moritz 对此进行了简要描述,并在下面进行了更详细的介绍.

当正则表达式引擎将正则表达式与输入字符串匹配时,它从正则表达式的开头和输入字符串的开头开始。

如果匹配失败,它将越过输入字符串中的第一个字符,放弃该字符,而是假装输入字符串从其 第二个 字符开始。然后它再次尝试匹配,从正则表达式的开头但输入字符串的第二个字符开始。它会重复此操作,直到到达字符串的末尾或找到匹配项。

根据您的示例,引擎无法在 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.

要对 @b 的元素执行“并行”最长匹配模式获胜 OR,请编写 @b(或 |@b在正则表达式中.

要对 @b 的元素进行“顺序”最左匹配模式获胜 OR,请在正则表达式中写入 ||@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 /
}