与えられた数未満の自然数の和を計算するプログラムの例を 1.4.2 で 紹介したが, これは自然数のリストを作るプロセスと, その要素の総和を計算 するプロセスのふたつからなっていた.
では少し問題を変えて, 与えられた数未満の自然数の平方の総和を計算するプ ログラムを考えてみよう. 前章のプログラムを利用して作るとすると, すぐ に思いつく方法は以下のふたつだろう.
与えられた数未満の自然数のリストを作るプログラムはもうある. リスト要 素の総和を求めるプログラムもある. とすると, 整数のリストをもらって, 各要素の平方を要素とするようなリストを作るプログラムをその間に入れてや れば解決である. たとえば以下のようなプログラムを作れば良い.
square([],Out) :- Out=[].
square([One|Rest],Out) :-
Square:=One*One, Out=[Square|OutTail], square(Rest,OutTail).
この述語を使えば, プログラム全体は以下のように書ける.
square_sum_up_to(N, Sum) :-
naturals(N,Naturals), square(Naturals,Squares), sum(Squares,Sum).
述語 square はリストを入力としてリストを出力するような述語を定義してい る. この述語の計算過程をプロセスととらえ, 入出力のリストをストリーム と解釈するとどうなるだろう. このような見方をすると, このプログラムは 一本のストリームから整数値のメッセージを受け, もう一本のストリームにそ の平方をメッセージとして送り出すプロセスを表している. このように, あ るストリームから受けとったメッセージになんらかの変換を施して, 別のスト リームに出力するようなプロセスを フィルタ (filter) と呼ぶ. 全 体のプログラムはプロセス naturals とプロセス sum が, フィルタ square を通るストリームを使って通信する, という構成になる (図 1.4).
この例ではフィルタとなったプロセス square は状態を持たず, 出力は入力メッ セージだけに依存している. 一般には, フィルタの動作は入力メッセージだ けではなく, フィルタ・プロセスの状態に依存しても良い. フィルタ・プロ セスは入力メッセージに応じて状態を変えられるから, 入力の履歴に応じてフィ ルタの仕方を変えることもできる.
フィルタは1本の入力ストリームと1本の出力ストリームを持つ. ふたつのフィ ルタの片方の出力をもう一方の入力につなげれば, 全体としてはやはり1入力1 出力のフィルタができる. この場合, 最初のフィルタがメッセージを次のフィ ルタに送ってしまった後, 次のフィルタがそのメッセージの処理をするのと並 列に, 最初のフィルタは次のメッセージの処理を行なえる. このようにフィ ルタをたくさんつなげていけば, パイプライン処理ができるわけである (図 1.5).