What is happening when my() is conditional?

南笙酒味 提交于 2021-02-07 11:22:29

问题


Compare using 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 and Bravo both complain about the global symbol not having an explicit package name, which is to be expected. But Charlie does not give the same warning, only that the value is uninitialized, which smells a lot like:

# case Delta
my $c;
print $c;

What exactly is going on under the hood? (Even though something like this should never be written for production code)


回答1:


You can think of a my declaration as having an action at compile-time and at run-time. At compile-time, a my declaration tells the compiler to make a note that a symbol exists and will be available until the end of the current lexical scope. An assignment or other use of the symbol in that declaration will take place at run-time.

So your example

my $c = 1 if 0;

is like

my $c;         # compile-time declaration, initialized to undef
$c = 1 if 0;   # runtime -- as written has no effect

Note that this compile-time/run-time distinction allows you to write code like this.

my $DEBUG;    # lexical scope variable declared at compile-time
BEGIN {
    $DEBUG = $ENV{MY_DEBUG};   # statement executed at compile-time
};

Now can you guess what the output of this program is?

my $c = 3;
BEGIN {
    print "\$c is $c\n";
    $c = 4;
}
print "\$c is $c\n";



回答2:


mob's answer is a great explanation of what currently happens (and why), but don't forget that perldoc perlsyn tells us:

NOTE: The behaviour of a my, state, or our modified with a statement modifier conditional or loop construct (for example, my $x if ... ) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.

Don't count on that result or the explanation for it still being true in future versions of Perl. (Although it probably will be.)




回答3:


The "my $foo = val if cond" construct and its undefined behavior has bitten me many times over the years. I wish the compiler could simply reject it (why keep something in the language that has undefined behavior?!), but presumably this cannot be done for backward compatibility or other reasons. Best solution I've found is to prevent it with perlcritic:

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



来源:https://stackoverflow.com/questions/11268367/what-is-happening-when-my-is-conditional

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!