ProgrammingPerl開発者 / Perlプロジェクトサポートの主任開発者

Perlにおけるレキシカルスコープと動的スコープの仕組み、my、local、ourが使用される際の違いを説明し、これらの違いを誤解した場合の問題の例を示してください。

Hintsage AIアシスタントで面接を突破

回答

Perlでは、変数はレキシカルまたは動的スコープを持つことができます。

  • myレキシカルスコープの変数を作成します:その変数は定義されたブロック内でのみ可視です。
  • local動的スコープのグローバル(パッケージ)変数の値を一時的に上書きします:新しい値はブロックを抜けるまで呼び出されたすべての関数で見えます。
  • ourはグローバル(パッケージ)変数を定義しますが、現在のレキシカルブロック内でのみ可視です。

例:

our $x = 10; sub test_my { my $x = 20; inner(); } sub test_loc { local $x = 30; inner(); } sub inner { print $x; } test_my(); # 10を出力 — my $xはinnerから見えません $| = 1; test_loc(); # 30を出力 — local $xはinnerから見えます

localは、特殊なグローバル変数$_、$/、$@などのパッケージ変数の値を変更するために使用されます。

ひっかけ問題

次のコードの実行結果は何ですか、そしてその理由は?

our $a = 5; sub outer { my $a = 10; inner(); } sub inner { print $a; } outer();

回答:5を出力します。なぜなら、outerのmy変数$aはinnerから見えず、ourで宣言されたパッケージ変数$aが使用されるからです。

このトピックの細かい違いを知らないことによる実際のエラーの例


事例

ログ解析スクリプトで、localを使用してグローバルハッシュに統計をログ記録したところ、ブロック内でのみ変更されると思っていましたが、localを介しての変更がプログラムの他の部分に広がり、データの損失を引き起こしました。

事例

モジュールテストで、多くの開発者がmyを使用してグローバルな特殊変数($/など)を上書きした結果、変更が行われず、テストが奇妙に部分的に失敗しました。

事例

JavaScript開発からPerlに移行した開発者は、経験から必要もなくあちこちでourを使って変数を宣言しようとしたため、予期しないグローバル変数が発生し、カプセル化や名前の衝突を妨げる結果となりました。