使用perl -w -Mstrict
进行比较:
# case Alpha
print $c;
...
# case Bravo
if (0) {
my $c = 1;
}
print $c;
...
# case Charlie
my $c = 1 if 0;
print $c;
Alpha
和Bravo
都抱怨全局符号没有明确的包名,这是可以预料的。但是Charlie
没有给出相同的警告,只是该值未初始化,这有点像:
# case Delta
my $c;
print $c;
引擎盖下究竟发生了什么? (即使不应该为生产代码编写类似的东西)
答案 0 :(得分:14)
您可以将my
声明视为在编译时和运行时具有操作。在编译时,my
声明告诉编译器记下符号是否存在,并且在当前词法范围结束之前可用。该声明中的符号的转让或其他用途将在运行时进行。
所以你的例子
my $c = 1 if 0;
就像
my $c; # compile-time declaration, initialized to undef
$c = 1 if 0; # runtime -- as written has no effect
请注意,这种编译时/运行时区别允许您编写这样的代码。
my $DEBUG; # lexical scope variable declared at compile-time
BEGIN {
$DEBUG = $ENV{MY_DEBUG}; # statement executed at compile-time
};
现在你能猜出这个程序的输出是什么吗?
my $c = 3;
BEGIN {
print "\$c is $c\n";
$c = 4;
}
print "\$c is $c\n";
答案 1 :(得分:6)
mob's answer对当前发生的事情(及其原因)有很好的解释,但不要忘记perldoc perlsyn
告诉我们:
注意:使用语句修饰符条件或循环结构修改的
my
,state
或our
的行为(例如{{1} }})未定义。my $x if ...
变量的值可能是my
,任何以前分配的值,或者可能是其他任何值。 不要依赖它。 perl的未来版本可能会有所不同 从你的perl版本开始尝试。这是龙。
在未来的Perl版本中,不要指望该结果或其解释仍然存在。 (虽然它可能会。)
答案 2 :(得分:2)
“我的$ foo = val 如果 cond ”构造及其未定义的行为多年来一直困扰我多次。我希望编译器可以简单地拒绝它(为什么保留一些具有未定义行为的语言?!),但是可能由于向后兼容性或其他原因无法做到这一点。我发现的最佳解决方案是用perlcritic来防止它:
http://search.cpan.org/perldoc?Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations