当記事は、「IBM i RiSING」2025年Aチームの成果物となる記事の一つです。
まとめはこちら
はじめに
RPGⅢとRPGⅣのフリーフォーム形式(以下FFRPG)の比較をしたいという大目標で、まずはRPGⅢ開発者とFFRPG開発者のメンバーでそれぞれブラックジャックアプリを作成しました。
今回は、まずRPGⅢ形式でブラックジャックを作成してから、FFRPG形式で同様の動作をするアプリを作成するという方法で比較しました。
以下からそれぞれ作成されたコードから言語的違いなど洗い出して比較していきます。
作成したもの
作成したコードは以下のリポジトリにまとめています。
https://github.com/risingc03a/rising-c03-a
1.文法上の違い・仕様書形式とフリーフォーム構文
RPG IIIは仕様書形式と呼ばれるコーディング様式で、行ごとに用途が決まっています。例えばファイル定義行(F仕様)、データ定義行(I仕様)、命令行(C仕様)など、各列に特定の意味があります。命令行では命令コード(例えばMOVELやZ-ADDなど)や条件判断(IF, DO等)を所定の列に記述し、対応するENDIFやENDDOも固定位置に書きます。
FFRPGではソース冒頭で**FREEを指定することで全行フリーフォーム形式で記述でき、欄割当について気にせずに記述可能です。例えばFFRPGのソースでは、条件分岐はC言語等に近い構文のIF...ENDIF;に置き換えられていて、論理条件についてもモダンな形式で記述されています。
RPG III (固定形式) の例
I---C *INKC IFEQ '1'
C SETON 90
C LEAVE
E---C ENDIF
FFRPG (フリーフォーム) の例
if *inKC = *on; // F3キーが押された場合
leave; // ループを抜ける
elseif *inKE = *on;
...
endif;
FFRPGでは文の終端にセミコロン;を置き、インデントでブロックを成形できます。コメントについても、RPG IIIでは行頭6番目の列にを置く形式でしたが、FFRPGでは//または/ ... */で記述でき、自由形式コード内に柔軟に配置できます。
命令語にも違いがあり、RPG IIIではZ-ADD(ゼロからの加算), MOVEL(左詰め移送)等の固有の命令コードを使用しています。FFRPGでは、代入(=)や組込み関数で表現できます。例えば数値の初期化は、RPGⅢでは各変数に対しZ-ADD *ZERO 変数の形式でゼロを代入していますが、FFRPGでは単に変数 = 0;と記述できます。同様に、文字列の初期化も、MOVEL *BLANK フィールド(ブランクで埋める)から、フィールド = *blanks;またはCLEAR フィールド;に置き換わっているなど、違いがあります。
それぞれ比較すると、RPGⅢは位置と用途が完全固定のため、慣れていれば目で型をなぞるように読むだけで理解しやすく、チーム内で固定形式に慣れたメンバーが多いと、表記ブレが少なく一定の安心感あるなどのメリットがあります。
FFRPGは、インデント・改行・コメント//で構造が直感的に見え、dcl-f / dcl-pr / dcl-s のように役割が単語で明示されるため、他言語経験者にも取り付きやすいといったメリットがあります。
2.GOTO文の有無・画面操作の違い・制御構文
RPG IIIでは GOTO/TAG が使えるので、短い分岐や早期脱出を最短の表記で書けます。小さな処理や短い分岐では記述が簡潔になる半面、ジャンプ点が増えると追跡コストが急増するという問題もあります。FFRPGではGOTOは使用不可能で、if/select/dow/for+leave/returnなどブロック構造がそのまま制御構造になります。
RPGⅢ版ではゲーム途中での処理ジャンプにタグLP01やLP2を用いていましたが、FFRPG版ではこれをループの制御で置き換えています。例えばプレイヤーが21を達成した場合、FFRPGソースではPCheck()関数が1を返すので、if PCheck() = 1; leavesr; endif;とし、サブルーチンgame1setから即座に抜けています。RPGⅢ版では同様の状況で一連の条件をチェックし、条件成立時にタグへのGOTOで後続処理をスキップしています。
C DLRCRD IFEQ 21
C GOTO LP2
C ENDIF
C ADD -10 DCEBX2
C ENDDO
C SUB DCEBOX DLRCRD
C ENDIF
C LP2 TAG
また、*INxx で表されるインジケータが画面やI/Oの状態やファンクションキーなどを示すフラグとして利用されていますが、RPGⅢ版では画面キーと処理分岐の共通レールになりがちで、UI変更が処理網に波及してしまいがちである欠点もあります。FFRPGでは明示的な変数などで代替が可能です。
3.プロシージャとローカル変数
プロシージャはFFRPGで利用できる、ひとまとまりの処理手順を必要に応じて呼び出せるようにしたものです。RPG IIIにもサブルーチンがありますが、FFRPGのサブプロシージャは引数と戻り値が使えるので、入力、出力がハッキリします。
またプロシージャではローカル変数が定義できます。ローカル変数は外部から直接参照することができない変数で、他の処理から誤って値を書き換えられることがない、各処理ごとで同名の変数でも名前衝突せず利用できるなどの利点があります。
FFRPGではPCheckやcalcAといったプロシージャを作成し、内部でdcl-sで定義した変数はプロシージャ内だけのスコープとして扱えます。
これらプロシージャとローカル変数についてはFFRPG独自の利点といえます。
プロシージャ定義の例
// A調整スコア計算
//---------------------------------------------
dcl-proc calcA export;
dcl-pi *n int(10);
Crd int(10) const;
Ace int(10) const;
end-pi;
dcl-s total int(10) inz(0);
dcl-s aces int(10) inz(0);
...
return total;
end-proc;
当記事の著作権はIBMに帰属します。詳細はこちらを参照ください。