我想在 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
]
最佳答案
TL;DR 推迟对 $<nr>
的评估直到评估正则表达式之后。 @JoKing++ 建议 one way .另一种方法是用大括号({$<nr>}
)包裹替换。
当您的原始代码调用 subst
时会发生什么
在 Raku 尝试调用 subst
之前例程,它将参数列表放在一起传递给它。
有两个值。第一个是正则表达式。它确实 不是 跑。第二个值为 $<nr>
.它评估为 Nil
因为,在程序开始时,当前匹配对象变量绑定(bind)到声称其值为 Nil
的对象。以及任何访问其中键值的尝试 -- $<nr>
-- 也返回 Nil
.所以,在 subst
之前,事情已经出了问题。永远运行。
一旦 Raku 组装了这个参数列表,它就会尝试调用 subst
.它成功了,subst
运行。
要获得下一场比赛,subst
运行正则表达式。这将更新当前匹配对象变量 $/
.但是现在对已经传递给 subst
的替换值做出任何改变已经太晚了。 .
火柴在手,subst
接下来看看替换参数。它发现它是 Nil
并采取相应行动。
第二次调用subst
, $<nr>
已采用 subst
的第一次调用的值.等等。
推迟评估 $<nr>
的两种方法
@JoKing 建议考虑使用 S///
.此构造首先评估正则表达式(在第一对 /
之间),然后是替换(在最后一对 /
之间)。 (如果您使用其他有效的 S
语法,如 S[...] = ...
,则同样的原则适用。)
如果您使用 subst
,然后,如上一节所述,Raku 在调用它之前将它的参数列表放在一起。它找到一个正则表达式(它不运行)和一个闭包(它也不运行)。然后它会尝试调用 subst
与这些论点并成功地这样做了。
接下来,subst
开始运行。它已收到匹配(正则表达式)和替换(闭包)的代码。
它运行正则表达式作为匹配操作。如果正则表达式返回匹配,则 subst
运行闭包并使用它返回的值作为替换。
因此,因为我们从传递 $<nr>
作为一个裸值,这意味着它被卡住为 Nil
, 传递它包裹在一个闭包中,这将其评估推迟到 $/
已设置为与填充的 <nr>
匹配入口,我们解决了问题。
请注意,这仅适用于设计/实现 subst
的人。足够聪明/好到允许匹配和替换参数都是 Code
的形式(匹配的正则表达式和替换的普通闭包)如果用户想要的话。然后它首先运行匹配,然后才运行替换闭包,如果它被传递一个,使用后一个调用的结果作为最终替换。同样,S///
之所以有效,是因为它被设计为仅在第一次评估替换后才评估替换。
关于raku - 在 for 循环中用 .subst 替换字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59867250/