はじめに
この文書は、マルチコア対応 Forth 系言語 Paraphrase での条件分岐処理はどのように書くのか? について説明します。
いわゆる普通の if
スタックの一番上にある値(TOS=Top Of Stack)が true の時のみ、ある処理を行う場合は、
if ある処理 then
と書きます。もちろん、ある処理の部分は複数のワードから構成されていても構いません。例として、TOS の絶対値を計算する abs というワードを定義してみます。
> "abs" : dup 0 < if -1 * then ;
ok.
> 5 abs .
5 ok.
> -5 abs .
5 ok.
TOS の値を複製(dup)しておき、その複製した値と 0 とを比べ、0 よりも小さい場合に限り、if 〜 then の間にある -1 を掛ける処理を実行します。正の場合は、if 〜 then の間は実行されないので、TOS の値は変化しないこととなります。
if - else
上の例は、ある条件を満たした時のみ特定の処理を実行するものでしたが、プログラムにおいては、ある条件を満たしているときは処理 A を、満たしていないときは処理 B を実行したい場合があります。これは C などでは if( 条件式 ) { 処理 A } else { 処理 B } などと書かれます。
Paraphrase でも、このような処理を記述できます(Forth でもできます)。以下の様に書きます:
if
TOS が true の時の処理
else
TOS が true でない時の処理
then
これを用いて、TOS の逆数を計算する rcp というワードを定義してみます。TOS が 0 の時は逆数を計算できませんので、このときは "ERROR" という文字列を TOS に積むこととします。
> "rcp" : dup 0 != if 1.0 swap / else drop "ERROR" then ;
ok.
> 2 rcp .
0.500000 ok.
> 0 rcp .
ERROR ok.
switch - case
Paraphrase でも他の言語同様、多方向分岐を行うための仕組みが用意されています。関連するワードは switch, case, ->, break, dispatch です。これについては、言葉で説明するよりも、以下の擬似コードを見たほうが分かりやすいかと思います:
switch
case TOS に対するテスト1 -> テスト1 が true の時に実行される処理 break
case TOS に対するテスト2 -> テスト2 が true の時に実行される処理 break
:
case TOS に対するテストN -> テストN が true の時に実行される処理 break
上記のテスト、いずれにも合致しない場合に実行される処理
dispatch
ある条件を満たした時に実行される処理が終了すると、dispatch の後に書かれた処理より実行が再開されます(dispatch の次に書かれている処理までジャンプします)。
有名な Fizz Buzz 問題(Wikipedia の説明へ)を処理するワード FizzBuzz は以下のように記述できます。このワードは、TOS が 3 の倍数なら "Fizz" を、5 の倍数なら "Buzz" を、3 および 5 の倍数(つまり 15 の倍数)であれば "FizzBuzz" という文字列をスタックに積みます:
"FizzBuzz" :
switch
case 15 % 0 == -> "FizzBuzz" break
case 5 % 0 == -> "Buzz" break
case 3 % 0 == -> "Fizz" break
dispatch
;
switch ブロックでは case は順次上から実行されていきますので、15 の約数であるか否かは最初に確認しなければなりません(でないと 5 の倍数もしくは 3 の倍数であると判断されてしまうので)。
実際のこのワードを用いて FizzBuzz 列を出力させると、以下のようになります。
> 1 20 for+ i FizzBuzz . next
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz ok.
その他
拡張辞書の extFactor を用いると、factor:if というワードを使用することもできます。これは Factor という連鎖性言語で使われている if 文と同様の条件判断を行うものです。こちらについては Paraphrase に同梱されているドキュメント docs/ext/extFactor.html を参照して下さい。