这里是第一个例子:
$g=5;
sub A {
my $x=2; # $x uses static scoping
local $y=3; # $y uses dynamic soping
local $g=7;
print "In A: g=$g, x=$x, y=$y\n";
B();
}
sub B {
print "In B: g=$g, x=$x, y=$y\n";
C();
}
sub C {
print "In B: g=$g, x=$x, y=$y\n";
}
A();
print "In main: g=$g, x=$x, y=$y\n";
这是第一个示例的输出:
In A: g=7, x=2, y=3
In B: g=7, x=, y=3
In B: g=7, x=, y=3
In main: g=5, x=, y=
这里是第二个例子:
sub big {
my $var=1;
sub sub1 () {
print " In sub1 var=$var\n";
}
sub sub2 () {
$var = 2;
print "In sub2, var is $var\n";
sub1();
}
sub1();
sub2();
sub1();
}
big();
这是第二个输出:
In sub1 var=1
In sub2, var is 2
In sub1 var=2
In sub1 var=2
问题是:为什么在第二个示例中sub B
和sub C
可以访问my $x=2;
,而在第一个示例中sub1()
和sub2()
无法访问my $var=1;
,我相信my
用于静态作用域在示例2的$x
静态范围内没有任何其他sub big
,我希望在第二个示例中没有输出,像这样:In sub1 var=
。在第二个示例中,sub1
和sub2
如何访问到$x
都已经用词my
声明了,为什么它的行为不像第一个示例?
所有词法变量(用my
声明的一个)仅在其最内层的代码块内可见。代码块是由{
... }
包围的语句列表或代码文件。
在您的第一个示例中,所有子例程都在文件的顶级定义。定义子例程的代码块是完全独立的,并且在那些子例程中声明的任何词法变量在其他任何子例程中都不可见。
在第二个示例中,您在子例程sub1()
中定义了子例程sub2()
和big()
。这意味着定义两个内部子例程的代码块在定义外部子例程的代码块内-因此,两个内部子例程可以看到在big()
中声明的任何词法变量(因为这些变量在任何地方都可见)在big()
的代码块中)。
不要将命名的subs放置在命名的subs中。
首先,它不会使它们成为私有。
$ perl -e'
use strict;
use warnings;
sub outer {
sub inner { print "inner\n"; }
}
inner();
'
inner
更重要的是,它将导致许多奇怪的行为。
$ perl -e'
use strict;
use warnings;
sub outer {
my ($x) = @_;
sub inner { print "inner $x\n"; }
inner();
}
outer(123);
outer(456);
'
Variable "$x" will not stay shared at -e line 7.
inner 123
inner 123
命名子例程在编译时捕获,因此inner
捕获在编译时退出的$x
。当outer
退出时,其$x
被新的$x
替换,从而中断outer
的$x
与inner
的连接。
总是使用use strict; use warnings;
。