比方说,我有一些
package Foo;
my $bar;
我怎么才能知道是否 $bar
被声明,而不管它是否未初始化?
在某种程度上,我认为这是有可能的,因为...。warnings
知道了warnings
知音 $bar
存在,所以你得到的只是一个未初始化的警告。
$ perl -wE'my $bar; print $bar;'
Use of uninitialized value $bar in print at -e line 1.
但是 once
警告类在这里知道,变量 $baz
甚至没有宣布。
$ perl -wE'my $bar; print $baz;'
Name "main::baz" used only once: possible typo at -e line 1.
Use of uninitialized value $baz in print at -e line 1.
同样。strict
就会停止编译,所以它也必须知道这一点(注意到 die
从来没有触发过)。)
$ perl -wE'use strict; my $bar; print $baz; die 42;'
Global symbol "$baz" requires explicit package name (did you forget to declare "my $baz"?) at -e line 1.
Execution of -e aborted due to compilation errors.
所以它也必须知道这一点。
PadWalker
可以检查哪些词法变量被定义了。
use PadWalker ':all';
my $foo;
my $level = -1;
while (my $pad = eval { peek_my(++$level) }) {
print "$_ is declared in scope $level\n" for keys %$pad;
}
$level is defined in scope 0
$foo is defined in scope 0
而不需要Padwalker(打印一次 "is lex")。
package Foo;
print "is lex\n" if eval('\\$' . __PACKAGE__ . '::foo') != \$foo;
my $foo;
print "is lex\n" if eval('\\$' . __PACKAGE__ . '::foo') != \$foo;
要说明的是,词汇变量并不是任何包的一部分 也不会与包系统有任何互动,这是一个完全不同的会计。不管任何包声明,它都属于它所在的范围。这个作用域要么是括号,要么是声明它的子程序,要么是文件。
你所展示的大多数例子(once
和 strict
)处理包变量。对于这一点,你可以直接在stash中查看是否定义了这个名字。
对于未初始化的情况,perl在尝试使用该变量时,会看到它没有值。
package Foo;
my $x;
my $eval_fmt = 'use strict; %s || 1';
eval( sprintf $eval_fmt, '$y' ) or warn 'No such variable: $y';
eval( sprintf $eval_fmt, '$x' ) and warn 'Variable $x exists';