2012-06-29 1 views
14

perl -w -Mstrictを使用して比較します、両方のグローバルシンボルは、明示的なパッケージ名を持っていない文句を言うmy()が条件付きで何が起こっていますか?

# 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; 

正確にフードの下で何が起こっていますか? (たとえこのようなものが生産コードのために書かれてはいけないのですが)

+1

ブラボー場合には、 '$のC 'は、字句'(0)... 'ブロックは、それがある場合にスコープされますそのブロックの外でそれを参照するエラー( 'use strict'のもと) – mob

+5

ところで、 'my $ c = 1 if 0; ... $ c ... 'は正式には定義されておらず(そのように文書化されています)、許可されず、望ましくない動作(クラッシュなど)が発生する可能性があります。さて、クラッシュすることはありませんが、それは可能です:) – ikegami

+1

@ikegamiうーん、それはperlsynの "ステートメント修飾子"セクションの下に記載されています。良いリマインダー! –

答えて

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"; 
+0

驚くべき答え!コンパイル時の区別は欠けていたキーでした。どうもありがとう! –

+4

あなたが言うように 'my'は実行時の効果を持ちますが、あなたはそれが何であるか言及しませんでした! [スコープの終了時に変数をクリアするために命令をスタックに置いた後、左辺値としてvarを返します。]これはおそらくあなたが言及していない方が良いでしょう。 :) – ikegami

6

mob's answer現在(と理由)が起こるが、perldoc perlsynを教えてくれることを忘れてはいけないものの偉大な説明です:

注:myの行動、state、またはourステートメント修飾子条件付きまたはループ構成(たとえば、my $x if ...)で変更された場合、は未定義です。 my変数の値は、 undef、以前に割り当てられた値、またはその他の値でもかまいません。 それに頼らないでください。 perlの将来のバージョンは、あなたがそれを試してみるperlのバージョンとは異なる何かをしているかもしれません( )。ここは龍です。

今後のバージョンのPerlでは、結果や説明がまだ真実であるとは考えていません。 (それはおそらくなりますが。)

2

「私の$ fooの= ヴァル指揮場合」を構築し、その未定義の動作が長年にわたって私に何度もかましています。私はコンパイラが単純にそれを拒否できればいいのですが(なぜ、未定義の動作をしている言語で何かを保つのですか?)、おそらくこれは下位互換性やその他の理由ではできません。私が見つけた最良の解決策はperlcriticでそれを防ぐためです:

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

+0

Perlcriticは決して最良のソリューションです。 – tchrist

+3

この毒性構築物が誤って使用されないようにしたい場合、私はどのような選択肢がありますか? –

関連する問題