未完成メッセージの使い方を覚えてしまうと, 章の最初に出てきたプログラム で, ディスパッチャとマージャ以降の部分を一緒にして次のように書きたくなる.
queer_sum(N,Ans) :-
naturals(N,Naturals), dispatch_sum(Naturals,Odd,Even,0,Ans),
square(Even), cube(Odd).
dispatch_sum([],Odd,Even,Sum,Ans) :- Odd=[], Even=[], Ans=Sum.
dispatch_sum([One|Rest],Odd,Even,Sum,Ans) :- One mod 2 =\= 0 |
Odd=[make(One,Ret)|OddTail],
dispatch_sum(Rest,OddTail,Even,Sum,Ans,Ret).
dispatch_sum([One|Rest],Odd,Even,Sum,Ans) :- One mod 2 =:= 0 |
Even=[make(One,Ret)|EvenTail],
dispatch_sum(Rest,Odd,EvenTail,Sum,Ans,Ret).
dispatch_sum(Rest,Odd,Even,Sum,Ans,Ret) :- wait(Ret) |
SumN := Sum+Ret,
dispatch_sum(Rest,Odd,Even,SumN,Ans).
square([]) :- true | true.
square([make(One,Square)|Rest]) :- true |
Square:=One*One, square(Rest).
cube([]) :- true | true.
cube([make(One,Cube)|Rest]) :- true |
Cube:=One*One*One, cube(Rest).
このプログラムによって実現されるプロセス・ネットワークは図 2.2 のようになる.
dispatch_sum/5及びdispatch_sum_6は, 二つの述語で一つのプロセスを実現し, 入力の分割と, square/1で実現されるプロセス及びcube/1で実現されるプロセスへの 要求メッセージ送出, そして平方と立方の合計の保持も行なっている. この場合はプログラム全体の規模が小さいので問題ないが, 一般に規模の大きなプ ログラムでこのような一人何役も兼ねたプロセスを多用すると, プログラム 全体の構造が見えにくくなる. 後に述べるようなサーバプロセスを作る必要性 のある場合はいざ知らず, プログラム全体を素直な木構造で表現出来る場合は, できる限りマージャ, フィルタ, ディスパッチャといった単純な構成要素から 考えた方が良い.
ネットワーク構造が大きくなってくると, 当然モジュール化が必要になる. 木構造のサブネットワークをモジュールとしてまとめ, メインネットワークのひとつの ノードと考えるのが便利である. このときも各サブネットワー クがマージャ, フィルタ, ディスパッチャなどの役割を果たすようにすると, プログラム全体がネストした木構造になり, 構造がわかりやすくなる.