在“foreach”循环中发生了什么样的本地化?

时间:2010-02-11 21:47:32

标签: perl localization scope

来自perldoc perlsyn关于Foreach循环的主题:

  

如果变量是先前的   用我的声明,它使用它   变量而不是全局变量,   但它仍然局限于循环。

但请考虑这个例子:

use Devel::Peek;
my $x = 1;
Dump $x;
for $x ( 1 ) { Dump $x }

SV = IV(0x8117990) at 0x8100bd4
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 1
SV = IV(0x8117988) at 0x8100bf8
  REFCNT = 2
  FLAGS = (IOK,READONLY,pIOK)
  IV = 1

看起来这些变量并不相同。这是文档中的错误,还是我错过了什么?

3 个答案:

答案 0 :(得分:5)

每个规则都需要它的例外,这是一个。在for循环中,如果循环变量是词法(用my声明),Perl将为循环中的当前项创建一个新的词法别名。 OP代码可以写成如下:

use Data::Alias 'alias';

my $x = 1;
for (2..3) {
    alias my $x = $_;
    # note that $x does not have dynamic scope, and will not be visible in 
    # subs called from within the loop
    # but since $x is a lexical, it can be closed over
}

编辑:上一个示例是在Perl伪代码中,为了清晰起见,修改了答案。

答案 1 :(得分:2)

正确地说,它应该被称为别名,以避免与local()混淆。 CPAN上有各种模块,可以让你在其他情况下进行别名。

答案 2 :(得分:-1)

首先,要意识到存在全局(包范围)变量并且存在词法变量。它们可以具有相同的名称。从现在开始,我将通过其完全限定名称$::x来引用全球$ x,这是“全球$ x包主”的缩写。

为了向后兼容,for循环使用本地化的全局变量,除非你另有说明,或者$ x已经被声明为lexical(没有意识到)。所以for $x (2..3) {}指的是本地化的$ :: x。 for my $x (2..3) {}指的是词汇$ x。在这两种情况下,它们都在循环中,有点像:

for (2..3) {
    my $x = $_;
    ...
}

除了$ _之外,别名是$ x,而不是复制。

我相信上面的解释了为什么当你使用Devel :: Peek时你得到不同的标量。由于词法没有等效local(),因此可能会在for循环内的词法填充上声明一个新的词法,就像上面的代码一样。

local($x)也会更改基础SV,因为它正在执行以下操作:

my $original = $x;
my $new;
*::x = \$new;

...

*::x = \$original;

即。创建一个新标量,将其插入符号表的$ x插槽,然后在范围完成时恢复旧标量。

但那真的只是假设。你必须深入研究代码才能找到答案。

说词汇“本地化为循环”的文档不应被视为文字local()。术语local令人困惑,因为其他语言,甚至Perl程序员,可以互换使用它来表示local()和“词法范围”。 local()可能更好地称为temp()。所以我认为这些文档在那里的术语有点草率。

相关问题