根据文档,类的Bool
方法Regex
...
与调用者的$ _变量匹配,对于匹配项返回True,对于不匹配项返回False。
但是,在这个例子中
$_ = "3";
my regex decimal { \d };
say &decimal.Bool;
Run Code Online (Sandbox Code Playgroud)
返回False
。另外,查看源代码,它说的还算合理,因为它将匹配$!topic
实例变量。但是,尚不清楚此变量将有效地对应于$ _,并且上面的示例似乎是这样说的。任何实际发生的想法?
简短的答案:该文档对于6.c来说是准确的,但是确切的语义并不像“调用者”那样简单(实际上,它存在真正奇怪的错误的风险)。改进的行为是:
/.../
和这样的形式构造的匿名正则表达式rx:i/.../
将捕获$_
和$/
,并在代码到达它们的位置(填充$!topic
问题中提到的变量)。Bool
并且sink
会引起对所捕获的匹配$_
,并且将所得到的存储Match
对象成$/
,只要它是可写的。由于此行为仅适用于匿名正则表达式,因此您需要编写:
$_ = "3";
my regex decimal { \d };
say /<&decimal>/.Bool;
Run Code Online (Sandbox Code Playgroud)
这是很长的答案。首先,Bool
-causes-matching行为的目的是为了使这样的事情起作用:
for $file-handle.lines {
.say if /^ \d+ ':'/;
}
Run Code Online (Sandbox Code Playgroud)
在这里,for
循环将填充topic变量$_
,并if
提供一个布尔上下文。最初的设计是.Bool
查看$_
调用方的。但是,这存在许多问题。考虑:
for $file-handle.lines {
.say if not /^ \d+ ':'/;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,not
是主叫方.Bool
的Regex
。但是,not
也将有其自己的$_
-与任何子例程中一样-将其初始化为Any
。因此,从理论上讲,匹配将不起作用。除此之外,因为实际实现的是遍历调用方,直到找到$_
包含定义值的!这听起来很糟糕。考虑如下情况:
sub foo() {
$_ = some-call-that-might-return-an-undefiend-value();
if /(\d+)/ {
# do stuff
}
}
$_ = 'abc123';
foo();
Run Code Online (Sandbox Code Playgroud)
如果内部的调用foo
返回一个未定义的值(也许是意外的),匹配将继续遍历调用者链,而$_
在的调用者中找到的值foo
。实际上,我们可以在调用堆栈中走很多个台阶!(此外:是的,这也意味着存在复杂的$/
结果,需要更新!)
先前的行为还要求$_
具有动态范围-即可供调用者查找。但是,具有动态作用域的变量会阻止大量分析(包括编译器和程序员的分析),因而无法进行优化。由于使用了很多习惯用法$_
,这似乎是不可取的(没有人希望看到Perl 6性能指南建议“不要with foo() { .bar }
在热代码中使用,with foo() -> $x { $x.bar }
而要使用”)。因此,6.d
更改$_
为常规词汇变量。
这6.D $_
作用域变化已经相当小现实世界的后果,但它确实事业的语义.Bool
和.sink
上Regex
进行检查,因为他们经常使用的东西的一个上依赖$_
是动态的。这反过来揭示了$_
我刚刚描述的“第一个定义的”行为-在这一点上,动态作用域的使用开始看起来更多是危险而不是好处!
新的语义意味着程序员编写一个匿名的正则表达式可以依靠它匹配$_
和更新$/
是在范围内可见他们写的正则表达式-这似乎很简单的解释,和-的情况下,他们最终以$_
这ISN”定义-不足为奇!
归档时间: |
|
查看次数: |
88 次 |
最近记录: |