来自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
看起来这些变量并不相同。这是文档中的错误,还是我错过了什么?
答案 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()
。所以我认为这些文档在那里的术语有点草率。