導入
メインフレームのPL/I開発において、データのコピーを繰り返すことはメモリとCPUリソースの無駄遣いになりがちです。特に大規模な行列演算やデータ加工を行う際、物理的にデータを移動させることなく、特定の要素だけを別名として扱いたいという場面に遭遇します。今回解説する「iSUB」指定を活用したDEFINED属性は、そんな課題を解決する極めて強力かつエレガントな手法です。
基礎知識
DEFINED属性は、ある変数を別の変数と同じ記憶領域に割り当てる機能です。ここで登場する「iSUB(i番目の添字)」は、親配列と定義配列の添字の関係を式で記述する仕組みです。例えば「1SUB」は親配列の第1添字、「2SUB」は第2添字を意味します。これを使うと、親配列の行や列を入れ替えたり、対角線上の要素だけを抽出したりすることが、コード上で「別名」を定義するだけで実現できます。
実装/解決策
iSUB指定を使用する際は、親配列の次元数と、定義する配列の添字の対応関係を正しく記述する必要があります。物理的なメモリの配置を再定義するのではなく、論理的な「写像(マッピング)」をコンパイラに教えるイメージです。これにより、転置行列のような複雑な構造も、元の行列を参照するだけで自動的に正しくアクセスできるようになります。
サンプルプログラム
以下のコードは、10×10の行列から「対角成分」を抽出し、さらに「行と列を入れ替えた転置状態」の配列を定義する例です。
/ サンプルコード:DEFINED iSUBによる行列操作 /
DCL MATRIX(10, 10) FIXED BIN(31); / 元となる10×10の親配列 /
/ 対角成分の抽出:親の(n, n)を子の(n)として定義 /
DCL DIAG(10) FIXED BIN(31) DEFINED(MATRIX(1SUB, 1SUB));
/ 行列の転置:親の(j, i)を子の(i, j)として定義 /
DCL TRANSPOSE(10, 10) FIXED BIN(31) DEFINED(MATRIX(2SUB, 1SUB));
/ 使用例:対角要素に値をセットすると、自動的にMATRIXにも反映される /
DIAG(5) = 99; / MATRIX(5, 5)が99になる /
TRANSPOSE(1, 2) = 50; / MATRIX(2, 1)が50になる /
応用・注意点
この手法は非常に強力ですが、可読性の低下という大きな代償を伴います。後任のエンジニアがコードを読んだ際、「なぜDIAGに値を代入しているのにMATRIXが変わるのか?」という混乱を招く可能性があるため、必ずコメントで「DEFINEDによる別名定義である」ことを明記してください。
また、現代の高級言語へ移行する際は、このトリッキーな手法をそのまま再現することは困難です。移行時には、この「ビュー」の概念をクラスのゲッター/セッターメソッドに置き換える設計が必要になります。現場のレガシーコードで見かけた際は、その「物理コピーを避ける」という意図を汲み取り、最適化の知恵として継承していくことが重要です。

コメント