はじめに
この文書では、マルチコア対応 Forth 系言語 Paraphrase にて、どのように新しいワードを定義するのか、その方法について説明します。
ワードとは
他の言語でいうところの関数のようなものです。「ようなもの」というのは、Forth 系である Paraphrase では、条件判断で使用する if や for ループにおける for なども全てワードで提供されているため、C や JavaScript などでいうところの関数とは少し性質が異なります。これは、即時実行属性という概念が関係してくるのですが、それはまた別の文書にて説明できれば、と思っています。
ワードの定義方法
ワードの定義は以下の書式で行えます(※ 「現時点では」という状況です。というのは、現バージョンでも実装されている無名ワードに名前を与えるという形で、ワード定義もできるよう、構想中です)。
"ワード名" : ワードで行う処理 ;
以下、例として Hello World と表示するワード hello を定義してみます。Paraphrase は Forth 系ですので、ボトムアップ方式でのプログラミングが適しているように思います。ですので、ここでもまずはワードの定義なしで、単に "Hello World" と画面に表示するコードを考えてみます。
"Hello World" と画面に表示するだけなら、"Hello World" という文字列をスタックに積み、スタックに積まれている値を表示するワード . (ピリオド)を実行すれば十分です。
> "Hello World" .
Hello World ok.
>
注:一番左側の不等号は Paraphrase インタプリタが出力するプロンプトです(=入力する必要はありません)。
Hello World という文字列の出力方法が分かったので、次にこの処理を hello というワードとしてワード化してみます:
> "hello" : "Hello World" . ;
ok.
>
無事、ワードの定義ができました。実際にこのワードを実行させてみると、
> hello
Hello World ok.
>
となり、目的通りの動作を得ることが確認できました。
再帰
Forth では再帰呼び出しを行うワードを定義する場合、少し工夫が必要でした。しかし、Paraphrase では特に意識することなく再帰処理を記述できます。再帰処理のよくある例として階乗計算がありますので、Paraphrase でも書いてみます:
"fact" : // n --- n!
dup 0 > if // n が 0 よりも大きか?
dup 1- fact * // n>0 ならば n*fact(n-1)
else
drop 1 // n が 0 よりも大きくない場合は n を捨てて 1 を積む
then
;
コメントを除くと fact のコードは短いので、1 行で以下のようにも書くことができます(もちろん、複数行で記述することも可能です)。
> "fact" : dup 0 > if dup 1- fact * else drop 1 then ;
ok.
> 5 fact .
120 ok.
> 0 fact .
1 ok.
>
上の例では、実行例として 5 の階乗と 0 の階乗を計算させています。それぞれ 120 と 1 という正しい値が得られています。
定義できないワード
現在の Paraphrase ではワード名の前方参照に関する機能がありません(ver.0.91.0 現在)。そのため、ワード A がワード B を呼び出し、ワード B がワード A を呼び出すような相互再帰の状態にあるワードは定義できません。今後のバージョンアップにより、解決していければ…と思っています。