检查用变量制作的正则表达式

dax*_*xim 7 raku

sub make-regex {
    my $what's-in-the-box = rand > .5 ?? 'x' !! 'y';
    /$what's-in-the-box/
}

my $lol-who-knows = make-regex;
$lol-who-knows.gist.say;
Run Code Online (Sandbox Code Playgroud)

您如何看待正则表达式(即xy)的内部结构?强制匹配不是解决方案。

rai*_*iph 6

您如何看待正则表达式(即xy)的内部结构?

你:

  • 静态编译正则表达式。这样做将涉及使用 raku 编译器,即 Rakudo。

  • 动态评估正则表达式,以便$what's-in-the-box您的正则表达式中的变量被插入并变成xor y。这样做将涉及将正则表达式作为代码运行。这反过来意味着使用 Rakudo 并使用Match对象调用者(或子类实例,或者可以想象,模拟对象等效物)运行正则表达式。

  • 查看生成的正则表达式。这样做将涉及使用编译器 (Rakudo) 工具链特定的内省或调试功能。

强制匹配不是解决方案。

如果您只是为了避免需要成功匹配,则可以在没有输入的情况下运行正则表达式:

say Match.new.&$lol-who-knows; # #<failed match>
Run Code Online (Sandbox Code Playgroud)

但它必须运行,否则$what's-in-the-box变量不会变成xor y。您可能认为您可以通过编写一些模仿 raku 正则表达式构造/使用的这一部分的东西来欺骗这一点,但有充分的理由认为这不会奏效[1]

然后,您必须在开始运行之后和完成运行之前,使用 Rakudo 工具链功能查看其内部结构。

正则表达式是一种方法

在 raku 中,aRegex是代码,是Method.

在您运行它之前,通过在匹配中使用它,该代码只是/$what's-in-the-box/(又名regex { $what's-in-the-box })。这相当于:

method {
  ...self should be a Match or a sub-class of it
  ...if self is not an instance, create a new one
  ...do matching -- compiler evaluates $what's-in-the-box during this
  ...return updated self / new instance
}
Run Code Online (Sandbox Code Playgroud)

(要查看更多细节,请参阅Moritz 对 SO Can I change the slang inside a method?的回答。)

例程是一个闭包

创建里面您正则表达式关闭命名make-regex。编译器会发现您使用过的内容$what's-in-the-box,因此即使在make-regex闭包返回后仍会保留该变量。后来,如果/是你的正则表达式时运行,该$what's-in-the-box变量将被其值代替此刻正则表达式运行

脚注

[1]如果您尝试使用编译器进行最终运行,您会遇到许多巨大的复杂情况。即使像插值这样简单的事情也不是微不足道的。引用Jonathan Worthington 的话,在 2020 年

我想哦,我只是在构建 [一个工具] 而不是真正的编译器。我可以......有一个更简单的符号分辨率模型。最后事实证明,不,我真的不能。这开始给我们带来一些问题。当我们使用编译器中使用的相同算法和查找结构调整我们解析符号的方式时,突然之间一切都变得简单了很多。