Val*_*kas 9 string-substitution raku
我想for使用命名捕获在块中进行字符串替换。我期望得到数字 1,2,3 作为输出。但它Nil用于第一次运行,然后是 1 和 2 用于第二次和第三次运行。如何.subst在循环结构中正确使用?当使用map构造而不是for循环时,我看到了相同的行为。如果我用固定的字符串值替换它,它确实按预期工作。
for <a1 b2 c3> -> $var {
say $var;
say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK
}
#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11
Output:
a1
Use of Nil in string context
in block at test3.pl6 line 3
b2
1
c3
2
]
Run Code Online (Sandbox Code Playgroud)
rai*_*iph 10
TL;DR推迟评估$<nr>直到评估正则表达式之后。@JoKing++ 建议一种方式。另一种方法是用大括号 ( {$<nr>})包裹替换。
subst在 Raku 尝试调用subst例程之前,它会将要传递给它的参数列表放在一起。
有两个值。第一个是正则表达式。它并没有运行。第二个值是$<nr>。它的计算结果为 ,Nil因为在程序开始时,当前匹配对象变量绑定到声称其值为 is 的东西,Nil并且任何试图访问其中的键值的尝试 - $<nr>- 也会返回Nil。所以在这一点上,在subst运行之前,事情已经出错了。
一旦 Raku 组装了这个参数列表,它就会尝试调用subst. 它成功了,并且subst运行了。
要获得下一场比赛,请subst运行正则表达式。这会更新当前的匹配对象变量$/。但是现在对已经传递给 的替换值产生任何影响已经太晚了subst。
有了 match,subst接下来看看替换参数。它发现它Nil并相应地采取行动。
对于 的第二次调用subst,$<nr>已采用 的第一次调用的值subst。等等。
$<nr>@JoKing 建议考虑使用S///. 此构造首先评估正则表达式(在第一对/s 之间),然后是替换(在最后一对/s 之间)。(如果您使用其他有效的S语法,如S[...] = ....,则同样的原则适用。)
如果您使用subst,那么,如上一节所述,Raku 在调用它之前将其参数列表放在一起。它找到一个正则表达式(它不运行)和一个闭包(它也不运行)。然后它尝试subst使用这些参数调用并成功调用。
接下来,subst开始运行。它已收到匹配(正则表达式)和替换(闭包)的代码。
它运行正则表达式作为匹配操作。如果正则表达式返回匹配,则subst运行闭包并使用它返回的值作为替换。
因此,因为我们从$<nr>作为裸值传递(这意味着它被冻结到Nil)切换到将它包裹在一个闭包中传递,这将它的评估推迟到$/已设置为与填充<nr>条目匹配时,我们解决了这个问题。
请注意,这仅有效,因为设计/实现的subst人足够聪明/足够好,允许匹配和替换参数都是Code(匹配的正则表达式和替换的普通闭包)的形式,如果用户想要的话。然后它首先运行匹配,然后才运行替换闭包,如果它被传递了一个,使用后一个调用的结果作为最终替换。同样,S///之所以有效,是因为它被设计为仅在第一次评估替换之后才评估替换。