PL/Iの「戻り値」を攻略せよ!RETURNS属性でスマートな関数プログラミングを始めよう
皆さん、こんにちは。メインフレームの世界へようこそ。
普段、JavaやCOBOLに触れていると、「関数が値を返すのは当たり前」ですよね。PL/I(ピー・エル・アイ)の世界でも、それはもちろん可能です。しかし、PL/Iは1960年代に生まれた非常に多機能な言語。少しばかり「独特の作法」が存在します。
今日は、PL/Iにおける関数型プロシージャの要である「RETURNS属性」について、現場でハマりやすいポイントを交えながら、優しく紐解いていきましょう。怖がる必要はありません。一つずつ見ていけば、とても論理的で美しい仕組みだと気づくはずです。
—
1. なぜ「RETURNS」が必要なのか?
Javaならメソッド定義で `public int calculate(…)` と書けば戻り値が整数だと伝わりますよね。でも、PL/Iは少し違います。PL/Iは極めて柔軟な言語であるがゆえに、「このプロシージャは値を返すのか、それとも単なる処理の実行(サブルーチン)なのか」を、コンパイラにハッキリ教えてあげる必要があるのです。
そのための魔法のキーワードが RETURNS属性 です。
—
2. 実践!RETURNSを使ったプロシージャの書き方
まずは、数値を2倍にして返すだけのシンプルな関数を見てみましょう。
1
/ プロシージャ定義:数値を2倍にして返す /
DOUBLE_VALUE: PROCEDURE(INPUT_VAL) RETURNS(FIXED BIN(31));
DCL INPUT_VAL FIXED BIN(31); / 引数の宣言 /
/ 計算結果を戻り値として返す /
RETURN(INPUT_VAL 2);
END DOUBLE_VALUE;
ここで注目してほしいポイント
- PROCEDURE(引数) RETURNS(型):
「このプロシージャは、計算が終わった後に、指定されたデータ型(今回は`FIXED BIN(31)`=Javaで言うところのint型のようなもの)を返しますよ」という宣言です。
- RETURN(値):
ここが出口です。`RETURN`文の括弧の中に、返したい値や変数を入れます。
—
3. 呼び出し側の「心構え」が重要
ここが一番の落とし穴です。PL/Iでは、呼び出し側(Caller)が「この関数はどんな型を返すのか」を知っていないと、コンパイラが「型変換」という名の大きなお世話(あるいは予期せぬ挙動)をしてしまうことがあります。
呼び出し側では、`DCL`(宣言)で戻り値の型を明示するのが、熟練アーキテクトの作法です。
1
MAIN_PROC: PROCEDURE OPTIONS(MAIN);
/ 呼び出す関数が「FIXED BIN(31)を返す」ことを明示する /
DCL DOUBLE_VALUE ENTRY(FIXED BIN(31)) RETURNS(FIXED BIN(31));
DCL RESULT FIXED BIN(31);
/ 関数の呼び出し /
RESULT = DOUBLE_VALUE(10);
PUT SKIP LIST(‘計算結果は: ‘ || RESULT);
END MAIN_PROC;
初学者が陥りやすい罠
もし呼び出し側で `DCL DOUBLE_VALUE ENTRY …` を忘れてしまうと、コンパイラは「デフォルトのルール(多くの場合、浮動小数点型など)」を勝手に適用しようとします。これが原因で、計算結果が突然おかしな値(桁落ちや型不一致)になるというトラブルが、現場ではよく発生します。
「呼ぶ側でも、どんな型が返ってくるか必ず教えてあげる」。これがPL/Iの安全な歩き方です。
—
4. なぜ「FIXED BIN(31)」のような書き方なのか?
Javaの `int` や `long` に慣れていると、`FIXED BIN(31)` といった記述は少し奇妙に見えますよね。これはメインフレームが「ビット単位、メモリ単位で徹底的に効率を追求する」マシンだからです。
- FIXED: 固定小数点数(整数)ですよ。
- BIN: バイナリ(2進数)形式で保持しますよ。
- (31): 31ビットの精度を確保してください(符号ビットを含めて32ビット=4バイト分)。
COBOLの `PIC S9(9) COMP` とほぼ同義だと思ってください。PL/Iは、ハードウェアの能力を最大限に引き出すために、データのサイズをプログラマが細かく指定できるのです。これも慣れてしまえば、「メモリを無駄にしない」という安心感に変わりますよ。
—
最後に:PL/Iは難しくない
今回紹介した `RETURNS` 属性は、プログラムの「入力」と「出力」を明確にするための重要な規約です。
- 定義側: `PROCEDURE(…) RETURNS(…)` で出口を定義。
- 呼び出し側: `DCL … RETURNS(…)` で期待値を教える。
このペアさえ守れば、PL/Iはあなたの意図を完璧に汲み取ってくれる、非常に堅牢で頼もしい相棒になります。もし、既存のソースコードで戻り値の型が分からず迷ったら、まずは定義元の `PROCEDURE` 文を探しに行ってみてください。
メインフレームの旅は始まったばかりです。また次回の記事で、より深いテクニックを一緒に学んでいきましょう!何か疑問があれば、いつでも現場の知見を共有しますからね。
