Raku is a match for *
— 焉知非鱼Raku Is a Match for *
PimDaniel 提出了一个有趣的问题。
我如何在匹配时测试 match is True : 这不起作用。
if my ($type,$a,$b,$c) = ($v ~~ /^ ('horiz'|'vertic') '_' (\d+) '_' (\d+) '_' (\d+) $/)>>.Str { ... }
好吧,我分2次做了1/捕捉并测试匹配,2/将匹配转换为Str。
没有得到及时的回答,完全没有改进。我也找不到一个好的方法来快速完成这个任务。事实上我花了一个小时才破解这个螺母。这里的主要问题是,一个失败的匹配会产生 .Str
会抱怨的 Nil。所以让我们把 if 的布尔检查和转换为 Str 的过程分开。
my $a = '1 B';
if $a ~~ /(<digit>) \s (<alpha>)/ -> $_ {
my ($one, $B) = .deepmap: *.Str;
say "$one $B";
}
# OUTPUT: 1 B
通过将条件表达式的结果强行放入主题中,我们可以在匹配的结果上运行任何方法,但前提是 Match.bool
返回 true。我没有 CS*
学位,但如果 Raku-signatures 不会变成 turing complete,我会非常惊讶。
if $a ~~ /(<digit>) \s (<alpha>)/ -> Match (Str() $one, Str() $B) {
dd $one;
dd $B;
}
# OUTPUT: "1"
"B"
if
块的签名将 Match
胁迫为一个列表。我们选择其中的两个元素,并将这些元素胁迫为 Str
。当然,我们可以根据捕获的位置来强制到任何我们喜欢的东西。
Raku 中的 Regexes 被编译成相同的字节码,然后程序的其余部分。事实上,语法只是一个具有有趣语法的类。这就是为什么我们可以轻松地在 regex 里面运行Raku 代码。这意味着我们可以把整个程序从内部翻出来。
my @a = <1 B 3 D 4>;
my @b;
my $hit;
for @a -> $e {
@b.push: ($e ~~ /(<alpha>) || { next } /).Str;
}
say @b;
# OUTPUT: [B D]
在这里,如果匹配不成功,我们就跳过 .push
,用 next
跳过循环体的其余部分。我们可以在 regex
内部发出任何控制异常。这意味着我们可以将整个过程粘在一个 sub
中,然后从 regex
中返回我们正在寻找的值。
sub cherry-pick-numeric(Str $matchee) {
$matchee ~~ m/(<digit>) && { return .Numeric }/;
Empty
}
@b = do .&cherry-pick-numeric for @a;
dd @b;
# OUTPUT: Array @b = [1, 3, 4]
Raku 已经酝酿了10年。这是一个巨大的任务。现在,困难的部分来了。我们必须从那庞大的语言中找到所有好的惯用法。好东西会降临到那些等待的人身上(IRC上)。
*) 阅读。不要相信我写的任何东西。你已经被警告了。
更新一下。
我以真正的懒惰方式,想出了一个办法,在本该完成的工作之后,把匹配变成一个惰性列表。
$a = '1B3D4';
my \ll := gather $a ~~ m:g/
[ <alpha> && { take $/<alpha>.Str } ]
| [ <digit> && { take $/.<digit>.Numeric } ]
| [ { say 'step' } ]
/;
say ll[0];
say ll[3];
# OUTPUT: 1
step
step
step
D
技巧是用 :g
副词强制匹配一直运行到字符串的末尾。这个运行将被 take
打断(通过抛出 CX::Take
),当从 gather
返回的 Seq
中询问下一个值时再继续。我不知道这是否是有效的内存思想。可能会有一个 Match
实例为每个 take
保留在身边。
原文链接: https://gfldex.wordpress.com/2021/03/11/raku-is-a-match-for/