PL/Iの「戻り値」で迷わない!RETURNS属性と暗黙変換の深淵へ
皆さん、こんにちは。メインフレームの世界へようこそ。
JavaやCOBOLの経験がある方にとって、PL/Iという言語は少し「古風で頑固な職人」のように見えるかもしれません。確かに、この言語は1960年代に生まれた非常に多機能な言語ですが、そのぶん「至れり尽くせり」な機能も多いんです。
今日は、PL/Iで関数(FUNCTION)を書く際に欠かせない「RETURNS属性」と、ちょっと困ったときのお助け機能である「暗黙の型変換」について、現場の知見を交えて紐解いていきましょう。
—
1. PROCEDUREを「値が返せる関数」にする呪文:RETURNS
Javaではメソッドの戻り値型を `public int getResult()` のように書きますよね。PL/Iでも考え方は同じですが、宣言の仕方が少しユニークです。
あるPROCEDUREが「値を返すこと」をコンパイラに宣言するには、`RETURNS` 属性を使います。
/i
/ 数値を返す簡単な関数 /
CALC_TAX: PROCEDURE(PRICE) RETURNS(FIXED BIN(31));
DCL PRICE FIXED BIN(31) BYVALUE;
/ 計算結果を戻り値として返す /
RETURN(PRICE 0.1);
END CALC_TAX;
ここで重要なポイントがあります。「戻り値の型(属性)」と「PROCEDUREの名前」をセットで定義するという感覚です。
なぜこれが重要なのか?
PL/Iのコンパイラは、呼び出し元でこの関数が使われたとき、「こいつはどんなデータが返ってくるのか?」を事前に知っておく必要があります。もし `RETURNS` を書き忘れると、コンパイラは「あ、こいつはデフォルトでFLOAT(浮動小数点数)を返すんだな」と勝手に推測してしまい、意図しないバグの温床になることがあります。
—
2. 「型が違っても動く」の正体:暗黙的変換の魔法
さて、ここからがPL/Iの「面白いところであり、怖いところ」です。
もし、`RETURNS(FIXED BIN(31))` で宣言した関数から、呼び出し元が `CHAR`(文字列)を期待して受け取ったらどうなるでしょうか?
/i
DCL RESULT CHAR(10);
DCL CALC_TAX ENTRY RETURNS(FIXED BIN(31));
/ ここで型が一致していない! /
RESULT = CALC_TAX(1000);
Javaならコンパイルエラーですね。しかし、PL/Iは「おっと、型が違うね。でも僕がうまく変換しておいてあげるよ!」と、暗黙的なデータ変換を行ってしまいます。
なぜ変換が起きるのか?
PL/Iは「どんなデータ型でも、適当なルール(変換表)に基づいて強引に結びつける」という設計思想を持っています。
- 数値を文字列に入れるなら、数値を文字の並びに変換する。
- 精度が高い型から低い型へ変換するなら、端数を切り捨てたり丸めたりする。
これは便利な反面、「なぜか期待した値と一桁違う」「小数点以下が消えた」といった、現場で最も頭を抱えるトラブルの原因になりがちです。
—
3. 実務で守るべき「3つの鉄則」
メインフレームの現場で、こういった「暗黙の仕様」に振り回されないために、ベテランのアーキテクトとして皆さんに伝えたい鉄則があります。
1. ENTRY宣言をサボらない
呼び出し側で `DCL CALC_TAX ENTRY RETURNS(…)` をしっかり書きましょう。これを書くことで、コンパイラが「型チェック」を行ってくれるようになり、不適切な変換を未然に防げます。
2. 型を合わせるのが正義
「PL/Iならやってくれる」と甘えず、できる限り `RETURNS` の型と、代入先の変数の型は一致させてください。これが最も安全で、かつ後からコードを読む人が苦労しない書き方です。
3. 明示的に変換する(BUILTIN関数)
どうしても型変換が必要な場合は、`FIXED` や `CHAR` などのビルトイン関数を使い、「意図して変換している」ということをコード上で明示しましょう。
—
まとめ:PL/Iは怖くない!
PL/Iの関数(PROCEDURE)における `RETURNS` は、ただの宣言ではありません。それは、コンパイラという強力な相棒に対して「この値はこういう型で扱うから、しっかりチェックしてくれよ!」と伝えるための大事な約束事なんです。
最初は少し窮屈に感じるかもしれませんが、型を厳密に意識し始めると、PL/Iはこれ以上ないほど堅牢なプログラムを書いてくれる信頼できる言語に変わります。
もし皆さんが現場で「戻り値がなんかおかしいな?」と思ったら、まずは `RETURNS` の属性指定を見直し、呼び出し側と受け取り側の型が本当に一致しているかを確認してみてください。
それでは、素晴らしいメインフレーム・ライフを!また次の技術解説でお会いしましょう。
