秋の訪れとともにやって来たRPGの新機能
今のようなパンデミックの最中には、少しでも気分を上げてくれるようなものがあるとうれしいものです。そんな折、「サンタのバーバラ」ことBarbara Morris氏とIBMトロント ラボの妖精エルフたちが、早めのクリスマス プレゼントを届けてくれました。7.3および7.4向けのPTFを通じて利用可能になる、これらの最新のRPG機能強化には、本物の宝石のような実に素晴らしい機能が散りばめられているようです。
これらの機能強化は、ほとんどがコードの可読性の改善に役立つものです。つまり、それらは、たとえばOpen AccessやDATA-INTOのような、まったく新しい機能を提供するものではないということです。その代わりに、それらの機能強化は、従来の処理を行うための、より効率的でより分かりやすいやり方を提供してくれます。それらがもたらす副次的なメリットとしては、他の言語でよく見られる機能を実装することで、RPGの初心者がこの言語へより移行しやすくなるという点も挙げられます。
まずは、そのような機能強化の2つについて、例を交えて見てみましょう。品目タイプ コードがあり、それらは「A」、「B」、「C」、または「Z」でなければならないとします。従来のIFステートメントで、コードが有効かどうかをチェックするとすれば、以下のようになるでしょう。
IF ( typeCode = 'A' ) or ( typeCode = 'B' )
or ( typeCode = 'C' ) or ( typeCode = 'Z' );
言うまでもなく、選択肢が多ければ多いほど、コードはひどいものになります。これを、新たなBIFの%LISTと新たなIN演算子を一緒に使用するやり方と比較してみます。ご覧の通り、コーディングが大幅に簡素化されます。
IF typeCode IN %List( 'A' : 'B' : 'C' : 'Z' );
さてどうでしょう。はるかにスッキリして、より分かりやすいのではないでしょうか。実に大きな改善だと私は思います。また、コードがリストにないかどうかテストしたい場合はさらに有用です。ただし、1つ注意点があります。最初に考えたのは、以下の1つ目の例のように、IFのすぐ後にキーワードNOTを追加すればよいというものでしたが、これは機能しません。そうする代わりに、2つ目の例のように、条件全体を括弧で囲み、結果をNOTで否定する必要があります。
// This version will not compile
IF NOT typeCode IN %List( 'A' : 'B' : 'C' : 'Z' );
// But this one does
IF NOT ( typeCode IN %List( 'A' : 'B' : 'C' : 'Z' ) );
考えてみれば当然のことですが、皆さんの最初の反応が私と同じであったらいけないので、触れておこうと思いました。
IN演算子にも%LISTにも、このようなテスト以外に、他の用途がありますが、率直に言って、それらの機能がこれですべてであったとしたら、私は十分にうれしいところなのですが、そうもいきません。まずは、%LISTから見てみましょう。
%LISTは、実際には一時的な配列を表すため、そのように使用することができます。たとえば、配列にロードできるようにしたい一連の非連続フィールドがある場合は、以下のように、%LISTを使用して作業を単純化することができます。
fieldArray = %LIST( Field1 : Field2 : Field3 : Field4 : Field5 );
この結果として、Field1の内容が要素1に、Field2が2つ目の要素(Field3以降も同様)に割り当てられることになります。こうしたほうが、連続的に個々の配列要素へ割り当てるのと比べて、はるかにスッキリして単純だと思われないでしょうか。
実際、%LISTオプションは非常に柔軟であるため、基本データ タイプが配列定義に一致していれば、単純なフィールドおよび定数だけでなく、式およびプロシージャー呼び出しも許容されます。たとえば、GetNearestWarehouse()によって返されるデータ タイプがwarehouseList配列のデータ タイプに一致する場合、次のコードはまったく問題なく機能します。
warehouseList = %List( preferredWarehouse
: GetNearestWarehouse(accountNumber)
: 'Chicago' );
%LISTが配列を表すことから、INを使用して従来の配列も検索できるのかどうか疑問に思われるかもしれません。もちろん、できます。以下は、「古い」方法でのやり方と、INオプションを使用したやり方を比較したものです。
If %Lookup( 'Two' : fieldArray ) > 0;
Dsply 'I found it!';
EndIf;
If 'Two' IN fieldArray;
Dsply 'I found it!';
EndIf;
このケースでは、リテラル「Two」を検索しましたが、検索引数は、検索される配列のデータ タイプに一致していればどのようなものでも構いません。あらためて言いますが、後者の方が、多少、単純で分かりやすくなっていると思います。
%LISTだけでなく%RANGEでも
新たなINオプションは、%LISTとともに使用することだけに制限されているわけではありません。INは、%RANGE BIFとともに使用することで、値が指定した範囲内にあるかどうかをテストするのにも使用することができます。以下に、その使用例を示します。
If orderValue IN %Range( minimumOrder : customerMaximum );
// Is equivalent to
If ( orderValue >= minimumOrder )
and ( orderValue <= customerMaximum );
範囲値は、リテラル、フィールド、名前付き定数などとすることができます。やはり、それらは比較値の基本データ タイプに一致する必要があるだけです。あらためて言いますが、これは以前にはできなかったことではありませんが、そうは言っても、大きな改善です。念のために言っておけば、%RANGEはinclusive(包含的)です。つまり、%RANGEはfromの値とtoの値を含みます。したがって、%Range( 3 : 6 )では、値3、4、5、および6がすべて範囲内とみなされます。
その他のサンタからのプレゼント
このパッケージには、この他にも2つの重要な機能強化があります。1つ目は、RPGへのFOR-EACHループの導入です。これは私がPHPで出会って以来ずっと待ち望んでいたものです。2つ目は、新たなコンパイラー オプションで、数値から文字への変換に関する問題を解決するためのものです。次回の記事では、これら両方の機能について取り上げる予定です。
機能強化のリスト全体、およびそれらの実装に必要なPTFについては、RPG Caféのページ( https://ibm.biz/rpg_cafe)を参照してください。
これらの新機能が、私が思っているのと同じくらい、皆さんのコーディングに役立つことを分かっていただければと願っています。