【PL/I学習|豆知識】PL/Iにおける「名前の重複(Shadowing)」を正しく理解し、予期せぬバグを防ぐ

導入

メインフレームのレガシーシステムを保守・開発する際、入れ子構造になったブロック内で変数を宣言することはよくあります。このとき、親ブロックと同じ名前の変数を再宣言すると、内側のブロックでは「新しい変数」が優先され、親の変数が隠蔽されます。これを「シャドーイング(Shadowing)」と呼びます。この仕様を理解していないと、意図せず親の値を破壊したり、計算結果が狂ったりする深刻なバグを引き起こす原因となります。本稿では、PL/Iにおけるこの挙動の仕組みと、安全なコーディングのための注意点を解説します。

基礎知識

PL/Iは「ブロック構造」を持つ言語であり、BEGINブロックやPROCEDUREブロックが入れ子状に構成されます。変数の有効範囲(スコープ)は、その宣言が含まれるブロック内です。内側のブロックで外側と同じ名前の変数を宣言すると、そのスコープ内では「内側の宣言」が有効となり、外側の変数は見えなくなります。これはJavaやC#のローカル変数によるフィールド隠蔽と同じ概念ですが、PL/Iの場合、変数だけでなく「ENTRY名」や「FILE名」までもが対象となるため、より広範な影響を考慮する必要があります。

実装と解決策

シャドーイングが発生する際は、コンパイラはエラーを出さずに「内側の変数が優先される」という仕様に従ってコードを生成します。そのため、開発者が「親の変数を操作しているつもり」でも、実際には「ローカルな別変数」を操作しているというケースが発生します。これを防ぐためには、可能な限り命名規則を統一し、グローバル(外側)とローカル(内側)で接頭辞を変えるなどの工夫が必要です。また、コードレビュー時には、意図しない再宣言が行われていないか注視することが重要です。

サンプルプログラム

以下のサンプルは、外側と内側で同名の変数「VAL」を宣言し、それぞれが独立して動作する様子を示しています。

/ サンプル:ブロックの入れ子による名前の重複 /
EXAMPLE: PROCEDURE OPTIONS(MAIN);

/ 外側のスコープの変数 /
DCL VAL FIXED BIN(15) INIT(100);

PUT SKIP LIST(‘外側でのVALの値:’, VAL);

BEGIN;
/ 同じ名前の変数を内側のブロックで宣言(シャドーイング発生) /
DCL VAL FIXED BIN(15) INIT(200);

/ ここでは内側の変数(200)が参照される /
PUT SKIP LIST(‘内側でのVALの値:’, VAL);
END;

/ ここでは再び外側の変数(100)が有効に戻る /
PUT SKIP LIST(‘ブロック終了後のVALの値:’, VAL);

END EXAMPLE;

応用・注意点

PL/Iの移行や大規模改修時において特に注意すべきなのは、変数名だけでなく「プロシージャ名(ENTRY)」や「ファイル名」の隠蔽です。外側で宣言された外部プロシージャ名を、内側のブロック内で変数名として再宣言してしまうと、そのブロック内からは元のプロシージャを呼び出せなくなります。これはリンクエラーや予期せぬ実行時エラーを引き起こす典型的な原因です。

現場での回避策として、大規模なソースコードでは、変数の命名に「スコープを示すプレフィックス(例:G_…はグローバル、L_…はローカルなど)」を付与することを強く推奨します。これにより、コードの可読性が飛躍的に向上し、シャドーイングによる事故を未然に防ぐことができます。

コメント

タイトルとURLをコピーしました