Perlでは、変数のスコープはキーワードmyとlocalによって定義されます。
myはレキシカルスコープを持つ変数を作成します(現在のブロック内でのみ有効)。localはグローバル変数の現在の値を一時的に保存し、ブロックの存在中に新しい値を設定します — 主にグローバル変数(例:$_、$/ など)で使われます。例:
my $x = 42; # 現在のブロック内でのみ見える { local $/ = undef; my $input = <STDIN>; # ここでの $/ は undef、ブロックの後に元の値に戻る }
myを使用する方が、より予測可能なスコープのため好まれます。
異なる2つのブロックで宣言された同じ変数にmyとlocalを使った場合、何が起こりますか?
多くの人は、
localとmyは同じように機能すると答えますが、そうではありません。localはグローバル変数(パッケージ変数)に対してのみ機能します。myで宣言された変数はlocalに対しては見えません。
例:
our $foo = "global"; { local $foo = "local"; print $foo; # "local" } print $foo; # "global" { my $foo = "lexical"; } # ブロック外の $foo はグローバルなもので、"lexical" ではない
物語
スクリプトで、myで宣言された変数を一時的に置き換えるためにlocalを使用したところ、何の結果も生まれず、内部モジュールのイベント処理にバグが発生しました。
物語
プロジェクトで、foreach内で$_をlocalで「ローカライズ」し、イテレータ用の$_を置き換えることを期待しましたが、foreachはすでに新しい$_を設定することを忘れていました。結果 — 機能しないフィルターと間違った反復ロジック。
物語
グローバルパッケージ変数がourで宣言されておらず、local $varを使用しようとした結果、strictやwarningのためにスクリプトがクラッシュし、デバッグに1日かかりました。