当我的()是有条件的时候会发生什么?

时间:2012-06-29 20:12:43

标签: perl

使用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;

AlphaBravo都抱怨全局符号没有明确的包名,这是可以预料的。但是Charlie没有给出相同的警告,只是该值未初始化,这有点像:

# case Delta
my $c;
print $c;

引擎盖下究竟发生了什么? (即使不应该为生产代码编写类似的东西)

3 个答案:

答案 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告诉我们:

  

注意:使用语句修饰符条件或循环结构修改的mystateour的行为(例如{{1} }})未定义my $x if ...变量的值可能是   my,任何以前分配的值,或者可能是其他任何值。   不要依赖它。 perl的未来版本可能会有所不同   从你的perl版本开始尝试。这是龙。

在未来的Perl版本中,不要指望该结果或其解释仍然存在。 (虽然它可能会。)

答案 2 :(得分:2)

“我的$ foo = val 如果 cond ”构造及其未定义的行为多年来一直困扰我多次。我希望编译器可以简单地拒绝它(为什么保留一些具有未定义行为的语言?!),但是可能由于向后兼容性或其他原因无法做到这一点。我发现的最佳解决方案是用perlcritic来防止它:

http://search.cpan.org/perldoc?Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations