これまでの例では, ストリームを流れるメッセージはすべてアトミックなデー タ (整数値や up, down などのアトム) だけだった. もちろんメッセージと してもっと複雑な構造を持つデータを流しても構わない.
よく使われるメッセージとしてファンクタ構造がある. ファンクタをメッセー ジとして用いて, ファンクタ名と引数個数でメッセージの種類を, 要素でメッ セージの詳細を表すのが便利である.
前述のカウンタをひとつずつではなく, 一度にいくつでも増減できるようにす るには, 増減のためのメッセージを引数を持つファンクタにして, 以下のよう に書けば良い.
counter(Stream):- counter(Stream,0). counter([],Count). counter([up(N)|Stream],Count) :- New:=Count+N, counter(Stream,New). counter([down(N)|Stream],Count) :- New:=Count-N, counter(Stream,New).
カウンタの値を読み取る機能は, 以下のようなファンクタをメッセージとする 節を追加すれば実現できる.
値を読み取るためのメッセージ show は, カウンタの値を返してもらうための 引数 V を未定義のままで送る. 受けとったプロセスは内部状態に応じてその 値を決めてやるわけである. このような未定義の部分を含んだメッセージを 未完成メッセージ (incomplete message) という. 未完成メッセージ も未完成データ構造の一種である. このようにすれば, 一本のストリームを 介して双方向の通信ができるわけである.counter([show(V)|Stream],Count) :- V=Count, counter(Stream,Count).
以上, ここではプロセスとストリームという概念を用いる KL1 のプログラミ ング・スタイルについて述べた. このプログラミング・スタイルの実現には 未完成データ構造が大切な役割を果たしている.