考虑以下代码
my $a = "AABBCCBGG";
say join "\n", do for $a.comb.squish {
$a ~~ s/^ ($_+) //;
}
与
my $a = "AABBCCBGG";
say join "\n", do for $a.comb.squish -> $b {
$a ~~ s/^ ($b+) //;
}
第一个永久挂起,而最后一个按预期执行。这是错误还是使用我不理解的隐式$ _时有更详细的信息?使用Rakudo Star 2019.03.01。
答案 0 :(得分:9)
您使用$_
的代码在道德上等同于:
/''+/
这将永远循环(因为空字符串''
匹配了无数次)。
(好,我只显示了一个简单的匹配,并且$_
必须分配或绑定到强制转换为字符串的某个值,否则将不会发生无限循环,因此您的代码必须经过处理使其循环两次,使其在道德上等同于上述内容,但这些都是红色鲱鱼。)
在使用我不理解的隐式
$_
时是否有一些更详细的信息?
smartmatch运算符的左侧别名为
$_
在代码中:
lhs ~~ rhs;
等效于:
$_ := lhs;
rhs.ACCEPTS(lhs);
我怀疑您没有考虑上述两行中的第一行。
(如果要避免这种主题化,只需单独使用第二行。 1 )
假设$_
被分配了一个定义的非空字符串:
s/$_//;
将总是更新$_
为空字符串(''
)。
并且:
$a ~~ s/^ ($_+) //;
将$_
别名为$a
,然后将$_
和$a
都更新为空字符串。
因此,第二次在for
循环中,~~
再次将$_
别名为$a
,该别名现在包含一个空字符串,然后到达无限循环条件是我的答案始于此。
1 在下面的评论中,Jo要求为什么 ~~
需要“主题化”(别名$_
为lhs)。权威的答案大概存储在@Larry的集体大脑中,可以用the P6 design documents来最好地表达(在页面搜索中“ smart match”和“ smartmatch”似乎是问题所在)。但我会就此事写自己的想法。
首先,aiui,不需要 这样。
Aiui @Larry可能已经决定,依赖于当前主题的构造(我认为这意味着//
,s///
和适当的例行调用)与P5一样。
以下是在P5(具有适当的编译指示)和P6中运行的一些代码:
my $a = 'a value';
$_ = 'another value';
say $a ~~ s/value/changed string/;
say $a;
say $_;
您期望结果如何?
在P5中:
a value
another changed string
在P6中:
「value」
a changed string
another value
P5保持$a
不变,修改$_
,然后将修改后的结果与原始$a
进行比较,得出结论不匹配(因此,say $a ~~ ...
行表示空行)。
P6在智能匹配期间将$_
别名为$a
,将$a
永久保留为s///
,并恢复$_
还原为之前的值。
如果我们坚持使用P5的方式,我们也将无法编写以下内容:
foo ~~ / ... /
,如果foo
与正则表达式匹配,则为真;
my $a = 'AA'; $a ~~ .uc
,并且在这段代码之前或之后,不管$_
的值是否为真;
foo ~~ .&bar
匹配项,其中bar
是期望参数的子项,我们希望它获得foo
。
与此同时,.ACCEPTS
也可用。因此,这不像您不能做与P5一样的事情。只是,默认情况下,如果人们首先不接触P5,并且@Larry
认为总体上是件好事,那么按照主题工作的结构可能就象人们可能期望的那样。 / p>
总而言之,乔,我听说P5做了您期望的工作,但是假设至少部分原因是您使用 P5并且您的期望基于在很大程度上考虑了它的作用,并在考虑了上述内容并给自己足够的时间来吸收它之后,想知道它是否仍然是您首选。我很乐意听到您关于一个月后的感觉的后续评论!
至少,这是我目前对此主题的想法。
答案 1 :(得分:4)
像往常一样,莱比的回答是正确的。我只添加一个小例子来证明他的话。
如果将示例更改为此:
my $a = "AABBCCBGG";
say join "\n", do for $a.comb.squish {
say "Pre-s/// $_";
$a ~~ s/^{say "Checking $_"} ($_+) //;
}
它将打印
Pre-s/// A
Checking AABBCCBGG
$a is
Pre-s/// B
Checking
然后挂起。在进入smartmatch之前,它会保留循环变量,但是一旦它进入smarmatch,它就会更改为正在进行smartmatch的内容,并且将整个字符串替换为空,因此$a
是第二次迭代,它挂断了。
结论:仅在非常确定没有在其他地方使用主题变量时,才使用主题变量。