perl6内插数组匹配AND,OR,NOT函数 [英] perl6 interpolate array in match for AND, OR, NOT functions

查看:64
本文介绍了perl6内插数组匹配AND,OR,NOT函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对数组中的所有匹配项,任何匹配项,任何不匹配项重新执行程序. 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)我最终要做的是将以前的代码压缩为两行:

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".但是我希望有一种更简单的方法,而不会出现聚集"和"for"循环.

非常感谢您提供任何见解.

lisprog

解决方案

与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)

,它是字符串"123 ab 4567 cde" not 23bcd567的12个匹配项的位置,由 s下方,它指向匹配的每个字符位置:

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

我正在尝试针对数组中所有匹配,所有匹配,无匹配项重新执行程序.

这些类似的声音交汇点以及您的其余部分显然都是关于交汇点的.如果您链接到现有程序,则可能会使我(他人)更轻松地了解您要执行的操作.

(1)

||@b匹配@b中的最左侧匹配标记,而不是最长之一.

|编写|@b,以匹配@b中最长的 匹配令牌.或者,更好的是,只写普通的@b,这是同一件事的简写.

这两个匹配模式(|@b||@b)与其他任何匹配模式一样,都受到regex引擎工作方式的影响,如Moritz所简要描述的,并在下面进行更详细的说明.

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

如果不匹配,它将越过输入字符串中的第一个字符,放弃该字符,而是假装输入字符串以其 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.

要对@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 /
}

I am trying to re-do my program for match-all, match-any, match-none of the items in an array. Some of the documentations on Perl6 don't explain the behavior of the current implementation (Rakudo 2018.04) and I have a few more questions.

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

> 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) is a Slip; how do I easily do OR or AND of all the elements in the array without explicitly looping through the array?

> 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) What I ended up doing is condensing my previous codes into 2 lines:

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;

output is "True" as expected. But I am hoping a simpler way, without the "gather-take" and "for" loop.

Thank you very much for any insights.

lisprog

解决方案

interpolate array in match for AND, OR, NOT functions

I don't know any better solution than Moritz's for AND.

I cover OR below.

One natural way to write a NOT of a list of match tokens would be to use the negated versions of a lookahead or lookbehind assertion, eg:

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

displays:

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

which is the positions of the 12 matches of not 23, b, cd, or 567 in the string "123 ab 4567 cde", shown by the line of ^s below which point to each of the character positions that matched:

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.

These sound junction like and some of the rest of your question is clearly all about junctions. If you linked to your existing program it might make it easier for me/others to see what you're trying to do.

(1)

||@b matches the leftmost matching token in @b, not the longest one.

Write |@b, with a single |, to match the longest matching token in @b. Or, better yet, write just plain @b, which is shorthand for the same thing.

Both of these match patterns (|@b or ||@b), like any other match patterns, are subject to the way the regex engine works, as briefly described by Moritz and in more detail below.

When the regex engine matches a regex against an input string, it starts at the start of the regex and the start of the input string.

If it fails to match, it steps past the first character in the input string, giving up on that character, and instead pretends the input string began at its second character. Then it tries matching again, starting at the start of the regex but the second character of the input string. It repeats this until it either gets to the end of the string or finds a match.

Given your example, the engine fails to match right at the start of 123 ab 4567 cde but successfully matches 23 starting at the second character position. So it's then done -- and the 567 in your match pattern is irrelevant.

One way to get the answer you expected:

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;

displays:

「567」

The use of :g is explained below.

(2)

|@b or ||@b in mainline code mean something completely unrelated to what they mean inside a regex. As you can see, |@b is the same as @b.Slip. ||@b means @b.Slip.Slip which evaluates to @b.Slip.

To do a "parallel" longest-match-pattern-wins OR of the elements of @b, write @b (or |@b) inside a regex.

To do a "sequential" leftmost-match-pattern-wins OR of the elements of @b, write ||@b inside a regex.

I've so far been unable to figure out what & and && do when used to prefix an array in a regex. It looks to me like there are multiple bugs related to their use.

In some of the code in your question you've specified the :g adverb. This directs the engine to not stop when it finds a match but rather to step past the substring it just matched and begin trying to match again further along in the input string.

(There are other adverbs. The :ex adverb is the most extreme. In this case, when there's a match at a given position in the input string, the engine tries to match any other match pattern at the same position in the regex and input string. It keeps doing this no matter how many matches it accumulates until it has tried every last possible match at that position in the regex and input string. Only when it's exhausted all these possibilities does it move forward one character in the input string, and tries exhaustively matching all over again.)

(3)

My best shot:

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 /
}

这篇关于perl6内插数组匹配AND,OR,NOT函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆