为什么$ main :: _在地图或循环中使用时引用词法$ _?

时间:2016-12-29 10:37:19

标签: perl scope

golfing down a solution的过程中,我偶然发现了这种看似奇怪的行为

我原以为$::_$main::_会引用全球$_,而不是环本地$_

  • $::_

    $ perl -E '$_=0; say $::_; say $::_ for 1..4'
    0
    1
    2
    3
    4
    
  • $main::_

    $ perl -E '$_=0; say $main::_; say $main::_ for 1..4'
    0
    1
    2
    3
    4
    

-MO::Deparse 下,两种表单的结果完全相同:

$ perl -MO=Deparse -E '$_=0; say $::_; say $main::_ for 1..4'
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
$_ = 0;
say $_;
say $_ foreach (1 .. 4);
-e syntax OK

更新

看起来明确声明$_循环变量my允许$main::_按预期工作:

$ perl -E '$_=0; for my $_ (1..4) { say $::_ }'
0
0
0
0

-MO=Deparse高兴地强调:

$ perl -MO=Deparse -E '$_=0; for my $_ (1..4) { say $::_ }'
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
$_ = 0;
foreach my $_ (1 .. 4) {
    say $main::_;
}
-e syntax OK

请注意,这是在Perl 5.16.3下,因此deprecation of my $_不适用。

问题

  • 这种行为是期待的吗?
  • 这种行为在Perl 5.24中是否有所不同?
  • 如何从循环内访问循环外声明的$_的值(因此循环打印0)?

2 个答案:

答案 0 :(得分:3)

  

是否需要这种行为?

是。你告诉循环使用$_又名$main::_ [1] 作为循环变量,所以它确实如此。

如果您希望它使用其他变量,则由您指定其他变量。

  

这种行为在Perl 5.24中有什么不同吗?

没有

  

我希望它能够从循环内访问循环外部声明的$ _的值(所以在循环中打印0)

为循环变量使用不同的变量,在循环之前复制$_,在循环之前引用$_,或导航堆栈以找到恢复$_的指令1}}。

  1. 正如perlvar中所述,对$_的无限制引用是指当前包中的$main::_,而不是$_

答案 1 :(得分:2)

是的,这是预期的。你的一个班轮等同于:

$_ = 0;
say $_;
{
    local $_;
    $_ = 1;
    while( $_ <= 4 ){
        say $_;
    }continue{
        $_++;
    }
}

Perl会在$_formap中对grep进行本地化,以便它们不会破坏其中已有的值。它对$a中的$bsort执行相同的操作。