根据 the documentation , Bool
Regex
的方法类(class)...
Matches against the caller's $_ variable, and returns True for a match or False for no match.
然而,在这个例子中
$_ = "3";
my regex decimal { \d };
say &decimal.Bool;
返回
False
.另外,looking at the source ,它说的有点道理,因为它将匹配 $!topic
实例变量。然而,不清楚这个变量是否会有效地对应于 $_,上面的例子似乎是这样说的。知道实际发生了什么吗?
最佳答案
简短的回答:文档对于 6.c 来说有点准确,但是确切的语义根本不像“调用者”那么简单(事实上,包含非常奇怪的错误的风险)。改进后的行为是:
/.../
的形式构成和 rx:i/.../
将捕获 $_
和 $/
在代码中到达它们时(填充问题中提到的 $!topic
变量)。 Bool
和 sink
将导致与捕获的匹配 $_
,并将存储结果 Match
反对那个 $/
,只要它是可写的。 由于此行为仅适用于匿名正则表达式,因此您需要编写:
$_ = "3";
my regex decimal { \d };
say /<&decimal>/.Bool;
这是长答案。
Bool
的目标-causes-matching 行为首先是为了让这样的事情起作用:for $file-handle.lines {
.say if /^ \d+ ':'/;
}
在这里,
for
循环填充主题变量 $_
,以及 if
提供一个 bool 上下文。原来的设计是.Bool
会看$_
来电者的。但是,这存在许多问题。考虑:for $file-handle.lines {
.say if not /^ \d+ ':'/;
}
在这种情况下,
not
是.Bool
的来电者在 Regex
.然而,not
也会有自己的$_
, 就像在任何子程序中一样 - 将被初始化为 Any
.因此理论上,匹配将不起作用。除此之外,因为实际实现的是遍历调用者,直到找到带有 $_
的调用者为止。包含一个定义的值!这听起来很糟糕。考虑这样一个案例:sub foo() {
$_ = some-call-that-might-return-an-undefiend-value();
if /(\d+)/ {
# do stuff
}
}
$_ = 'abc123';
foo();
在
foo
内部调用的情况下将返回一个 undefiend 值 - 也许是出乎意料的 - 匹配会继续沿着调用者链走,而是找到了 $_
的值。在 foo
的来电者中.事实上,我们可以在调用堆栈中深入很多层! (旁白:是的,这也意味着 $/
也需要更新结果的复杂性!)之前的行为还要求
$_
具有动态范围 - 即可供调用者查找。但是,具有动态范围的变量会阻止大量分析(编译器和程序员的分析)以及优化。许多成语使用 $_
,这似乎是不可取的(没有人希望看到 Perl 6 性能指南建议“不要在热代码中使用 with foo() { .bar }
,而是使用 with foo() -> $x { $x.bar }
”)。因此,6.d
已更改 $_
成为一个常规的词法变量。那个 6.d
$_
范围变化对现实世界的影响相当小,但它确实导致了 .Bool
的语义。和 .sink
在 Regex
需要检查,因为它们是依赖 $_
的一个经常使用的东西。动态。这反过来揭示了我刚刚描述的“第一个定义的 $_
”行为——在这一点上,动态范围的使用开始看起来更像是危险而不是好处!新语义意味着编写匿名正则表达式的程序员可以依赖它匹配
$_
并更新 $/
在他们编写正则表达式的范围内可见 - 这似乎更容易解释,并且 - 在这种情况下,他们最终会得到 $_
这没有定义 - 不那么令人惊讶!
关于regex - 在 Regex 上调用 Bool 无法按文档工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56815925/