問題の歴史:
Perlでは、最初からグローバル変数とローカル変数の両方が活発に使用されてきました。その後、myキーワードを使ってレキシカル変数が導入されました。これにより、開発者は変数のスコープを制御し、名前の衝突を防ぐための便利なツールを得ることができました。
問題:
グローバル変数(パッケージ変数)とレキシカル変数の混乱、localとmyの誤った使用、コード実行中のグローバル値の置き換えによって、エラーが頻繁に発生します。大規模なプロジェクトでは、スコープ管理の不注意が難解なバグにつながる可能性があります。
解決策:
myを使用してレキシカルスコープ(宣言されたブロック内のみで有効)の変数を宣言し、グローバル変数は必要に応じてのみ使用します。グローバル変数の一時的な値の置き換えにはlocalを使用し、ブロックの終了まで元の値を保持します。パッケージ変数にはourを使います。これらの違いを正しく理解することで副作用を避けることができます。
コード例:
our $global = 10; sub demo { my $lexical = 20; local $global = 99; # 一時的にglobalを変更 print "demo内部: $global, $lexical "; } demo(); print "demo外部: $global ";
主な特徴:
myは現在のブロック内でのみ可視な変数を作成しますlocalはグローバル変数を一時的に変更しますourは現在のファイルを超えて使用されるパッケージ変数を宣言しますmyで宣言された変数は現在のブロックの外でアクセスできますか?
いいえ。レキシカル変数myは、作成されたブロック内でのみ見え、ブロックの外では存在しません。
localとourの違いは何ですか?
localは、ブロックの間にグローバル変数の値を一時的に変更し、ourはパッケージ全体で可視な変数を宣言し、値のコピーを作成しません。
コード例:
our $var = 1; # パッケージのグローバル変数 sub test { local $var = 3; # 一時的に$varを3に置き換え print $var; }
evalの内側でmyを使用すると、変数はevalの外で見えるようになりますか?
いいえ。evalの内側でmyで宣言された変数は、そのevalブロック内のみにスコープが制限されます。
myとlocalの混乱、これらのキーワードの動作の誤解ネガティブケース
大規模なPerlプロジェクトで、明示的なスコープ指定なしでグローバル変数が広く使用されていました(myやourなしに)。ある時、新しい開発者がモジュール内でそのような変数の1つを誤って上書きしてしまい、プロダクションで予測不可能な結果を引き起こしました。
利点:
欠点:
ポジティブケース
新しいプロジェクトでは、すべての変数が関数やブロック内でmyを使って宣言され、グローバル変数は必要に応じてのみourを通じて使用され、明確なドキュメンテーションが用意されていました。
利点:
欠点: