RPGのSelect命令が魅力的にアップグレード
私は、以前からずっとRPGのSelect命令のファンでした。Ifステートメントをコーディングしていて、If-Else条件以外の3つ目の状況がある可能性があると思ったときはいつも、私はためらうことなく、Ifステートメントの代わりにSelect命令をコーディングします。RPG言語のSelect命令には、 V7R5 TR2およびV7R4 TR8でかなり素晴らしいアップグレードがなされました。Selectステートメントは、値を指定できるようになり、Select命令内で2つの新たな命令コード、When-isとWhen-inを使用できるようになっています。
免責事項:このテスト プログラムでは、キノコの可食性について取り扱われていますが、これは、あくまでプログラムの動作の仕組みを分かりやすく説明するためのものです。キノコの可食性については、ミズーリ州自然保護局(MDC)発行の「 A Guide to Missouri's Edible and Poisonous Mushrooms(ミズーリ州の食べられるキノコと毒キノコのガイドブック)」を参考にしましたが、実際に野生のキノコ類を採取したり摂取したりする際は、事前にご自身で十分に調べて、安全性が確保されるようにしてください。
まず、Select行に対する変更が、コードでどれくらい繰り返しを減らす(そして、私に言わせれば、コードを読みやすくする)ことができるかについて見てみましょう。この機能強化以前には、1つの値または配列内の変数の大文字をテストする必要がある場合は、次のようにSelectステートメントを書いていました。
Dcl-Proc known_safe_mushrooms;
Dcl-Pi known_safe_mushrooms Ind;
p_new_mushroom Char(20);
End-Pi;
Dcl-S safe_mushrooms Like(p_new_mushroom) Dim(3);
safe_mushrooms = %List('SHIITAKE':'PORTOBELLO':'MOREL');
Select;
When %Upper(p_new_mushroom) = 'CHANTERELLE';
Return *On;
When %LookUp(%Upper(p_new_mushroom):safe_mushrooms) > 0;
Return *On;
Other;
Return *Off;
EndSl;
Return *Off;
On-Exit;
End-Proc known_safe_mushrooms;
2つのWhenステートメントを「Or」で連結することもできましたが、コードの説明上の理由から、それらを別々にしておきました。問題は、テストする条件ごとに、%Upper BIFの使用を繰り返す必要があるということです。では、上のSelectステートメントを改良したものを見てみましょう。
Dcl-Proc known_safe_mushrooms;
Dcl-Pi known_safe_mushrooms Ind;
p_new_mushroom Char(20);
End-Pi;
Dcl-S safe_mushrooms Like(p_new_mushroom) Dim(3);
safe_mushrooms = %List('SHIITAKE':'PORTOBELLO':'MOREL');
Select %Upper(p_new_mushroom);
When-in safe_mushrooms;
Return *On;
When-is 'CHANTERELLE';
Return *On;
Other;
Return *Off;
EndSl;
Return *Off;
On-Exit;
End-Proc known_safe_mushrooms;
上の例では、Selectの行で、%Upper BIFを一度コーディングしただけである点に注目してください。そして、後続するすべての条件は、渡されたパラメーターの大文字の値でテストすることになります。
次に、配列safe_mushrooms内にその値があるかどうかテストするために、2つのBIFを入れ子にする必要性をなくすことができ、代わりにWhen-inステートメントを使用することができた点に注目してください。どう思われるでしょうか。もちろん、望ましい結果を得るためにBIFを入れ子にすることは苦になりませんが、これでコードが読みやすくなると思います。新たなRPGプログラマーがコードを読む必要がある場合は特にそうです。
そして、2つ目のWhenステートメントも、もうひとつの%Upper BIFの必要性がなくなるため、より簡潔になっています。私は、When-inおよびWhen-isによって、RPGがより自己説明的に見えるようになっているところが気に入っています。
When-is節は、条件を真であるか偽であるか評価するので、とりわけ有用です。前の例では、そっくりそのままの値があるかテストしましたが、真または偽の結果を返す式を使用できるようになりました。詳しく見てみましょう。
Dcl-Proc Demo_Select;
Dcl-s new_mushroom Char(20);
Dcl-s probably_safe Ind;
Select %Upper(new_mushroom);
When-is 'MOREL';
probably_safe = *On;
When-is known_safe_mushrooms(new_mushroom);
probably_safe = *On;
When-in %Range('BOLETE':'CHANTERELLE');
probably_safe = *On;
When-in %List('SHIITAKE':'PORTOBELLO');
probably_safe = *On;
Other;
probably_safe = *Off;
EndSl;
End-Proc Demo_Select;
この例では、%Upper BIFをSelect命令全体で一度使用するやり方を示しています。When-isステートメントは、1つの値をテストするのとともに、前の例のプロシージャーを呼び出すためにも使用されています。その次は、When-inステートメントの2つのバリエーション、すなわち、%Range BIFを使用しているものと、%List BIFを使用しているものです。
ここまでのところは、うまくできたと言えるでしょう。でもちょっと待ってください。それだけではありません。ここまでの例で示したのは、SelectステートメントでのBIFの使用法でした。このステートメントでは、任意の式の組み合わせを評価することもできます。たとえば、ユーザーに未分類のキノコを尋ねる別のプロシージャー、ask_user_for_mushroom()があり、ユーザーがグリーン スクリーン アプリケーションまたはWebアプリケーションなどで入力した内容について、Select命令の評価を行うとしたら、どうなるでしょう。
Dcl-Proc Demo_Select;
Dcl-s new_mushroom Char(20);
Dcl-s probably_safe Ind;
Select %Upper(ask_user_for_mushroom());
When-is 'MOREL';
probably_safe = *On;
When-is known_safe_mushrooms(new_mushroom);
probably_safe = *On;
When-in %Range('BOLETE':'CHANTERELLE');
probably_safe = *On;
When-in %List('SHIITAKE':'PORTOBELLO');
probably_safe = *On;
Other;
probably_safe = *Off;
EndSl;
End-Proc Demo_Select;
このSelectステートメントでは、テストしたいキノコをユーザーに尋ね、ユーザーが入力したものをすべて大文字にして、テストを行うことができます。私の記事をいつもお読みいただいている方ならご存じかと思いますが、私はプロシージャー主導型RPGの大ファンです。そして、これは、テストするキノコを受け取るためのプロシージャーで、カプセル化する必要があるビジネス ロジックをすべてカプセル化している良い例と言えます。もっとも、ここではそうしたビジネス ロジック自体は重要ではありませんが、かなり素晴らしい例だと思います。
なお、%Subarr BIFも、When-inステートメントで使用することができます。キノコ狩りではありませんが、%Subarrの用法や用例については、それぞれご自分で拾い集めていただければと思います。
これは、いろいろと使い途がありそうな機能強化であるような気がします。