【问题标题】:perl closures and regexp variablesperl 闭包和正则表达式变量
【发布时间】:2011-01-27 21:16:08
【问题描述】:

我在 perl 的闭包和 $1 regexp 变量中发现了一个可能的错误。简单地说,它们不会混合在一起。

让我们来看看这段代码。

use warnings;

while ("1234567890"=~/(.)/sg) {
    push @subs, sub{print $1;};
}

for (@subs) {$_->()}

您会想象 perl 现在会打印所有数字 - 相反,我收到了来自 undefined $1 的 10 条警告。

这真的是一个错误,还是我只是错过了 perl 文档中的某些内容?有什么原因吗,为什么$1 应该是未定义的,而不是闭包的一部分?

【问题讨论】:

    标签: perl


    【解决方案1】:

    Perl 有两个独立但在很大程度上兼容的变量系统。全局变量,在符号表中,词法变量在范围绑定的词法填充中。

    全局变量可以是符号解引用的目标,并受制于local 的动态范围。词法变量(使用my 定义)可以关闭。

    正则表达式匹配变量(以及所有 Perl 的其他特殊变量)是符号表中的全局变量,因此无法关闭它们。

    要解决这个问题,只需将值复制到词法中:

    use warnings;
    
    while ("1234567890"=~/(.)/sg) {
        my $x = $1;                # creates a new lexical that the sub closes over
        push @subs, sub{print $x;};
    }
    
    for (@subs) {$_->()}
    

    【讨论】:

    • 也感谢您的回答。我为尼龙添加了最佳答案,因为他速度更快,分数更少:) 我不能选择 2 个最佳答案
    • 匹配变量更奇怪的是,它们就像全局变量一样,是自动本地化的,除了递归函数。
    【解决方案2】:

    我认为答案类似于perl closures and $_ 的答案。 $1 也是一个全局变量。

    你需要做的是:

    my $x = $1;
    push @subs, sub{print $x;};
    

    【讨论】:

    • 哦,是的,这是有道理的 :) 但我认为你需要 print $x。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    相关资源
    最近更新 更多