我对以下两个代码段之间的行为差异感到困惑:
$x = 8;
sub a {
sub b {
print "B: $x\n";
}
my $x = 3;
&b();
}
&a();
和
$x = 8;
sub a {
my $x = 3;
sub b {
print "B: $x\n";
}
&b();
}
&a();
当第一个输出B:8时,第二个输出B:3。它们不应该输出相同的值,因为sub b的外部范围应该是sub a?功能的不同位置如何产生影响?
答案 0 :(得分:5)
其他人已经指出了嵌套sub
的问题,但这是我对你的问题理解的答案:
my
声明的“范围”在包含my
的语句之后开始,而不是在它出现的块的开头。或者,这两个都可以工作:
$ perl -wMstrict -le 'sub foo { my $bar="quz"; print $bar; } foo()'
quz
$ perl -wMstrict -le 'sub foo { print $bar; my $bar="quz"; } foo()'
Global symbol "$bar" requires explicit package name (did you forget to declare "my $bar"?) at -e line 1.
Execution of -e aborted due to compilation errors.
另外,请注意以下事项:
my $x = 3;
{
my $x = $x + 5;
print "1: $x\n"; # prints "1: 8"
}
print "2: $x\n"; # prints "2: 3"
在您的第一段代码中,在您声明sub b
时,Perl只知道全局$x = 8
,这就是print "B: $x\n"
正在使用的内容。在第二段代码中,Perl看到了my $x = 3
,所以它就是它的用途。如果您不使用嵌套的sub
s:
my $x = 8;
sub a {
my $subb = sub {
print "B: $x\n";
};
my $x = 3;
$subb->();
}
a(); # prints "B: 8"
和
my $x = 8;
sub a {
my $x = 3;
my $subb = sub {
print "B: $x\n";
};
$subb->();
}
a(); # prints "B: 3"
答案 1 :(得分:3)
这个问题源于嵌套的命名subs。
没有理由在Perl中使用嵌套的名称subs,因为内部sub不以作用域为外部。
相反,请使用:
sub p {
my ($x) = @_;
local *q = sub {
say $x;
};
q();
}
p($_) for 3, 4;
或
sub p {
my ($x) = @_;
my $q = sub {
say $x;
};
$q->();
}
p($_) for 3, 4;