Prolog では、リスト構造を次のように記述する。
[] ... 空のリスト [a] ... 1つの要素aから成るリスト(長さ1のリスト) [a,b] ... 2つの要素aとbから成るリスト(長さ2のリスト) [a,b,c] ... 3つの要素aとbとcから成るリスト(長さ3のリスト) |
リストの操作は、変数のマッチングによる。
[X] ... 1つの要素から成るリストとマッチ [X|Y] ... 1つ以上の要素から成るリストとマッチ ◎ 長さ1のリストとマッチしたとき、X は先頭の要素、Y は []。 ◎ 長さ2以上のリストとマッチしたとき、X は先頭の要素、 Y は2番目以降の要素から成るリスト [X,Y|Z] ... 2つ以上の要素から成るリストとマッチ ◎ 先頭要素は X、2番目の要素は Y、 3番目以降の要素から成るリストは Z にマッチ |
では、次のプログラムを入力(コピー)してみよう。 事実は、今年のF1グランプリについて、開催国とその結果を表している。 リストは、レース結果で、入賞者(第1位から第8位まで)の人物の略称である。 たとえば、アメリカグランプリのデータは gpx(america, ...) の部分が表している。 優勝者は、ham (ルイス・ハミルトン)である。 また、第2位はalo(フェルナンド・アロンソ)、 第3位はmas(フェリペ・マッサ)である。
規則 winner_in は、開催国と優勝者の関係を表す規則である。なお、アンダーバーは、特別な変数で、バインド値が返されず、1行の中で複数回使われても、互いに関係を持たない。
gpx(australia,[rai,alo,ham,hei,fis,mas,ros,rsh]). gpx(malaysia, [alo,ham,rai,hei,mas,fis,tru,kov]). gpx(bahrain, [mas,ham,rai,hei,alo,kub,tru,fis]). gpx(spain, [mas,ham,alo,kub,cou,ros,kov,sat]). gpx(monaco, [alo,ham,mas,fis,kub,hei,wur,rai]). gpx(canada, [ham,hei,wur,kov,rai,sat,alo,rsh]). gpx(america, [ham,alo,mas,rai,kov,tru,web,vet]). gpx(france, [rai,mas,ham,kub,hei,fis,alo,but]). winner_in(W,C) :- gpx(C,[W|_]). |
次の質問をしてみよう。この質問の意味は、アメリカグランプリの優勝者Wは誰であるかを求めることである。
?- winner_in(W,america). |
aloが優勝した国を求める質問はどのようにすれば良いか? 答え ⇒
開催国と第2位の関係を表す規則 second_winner_in(W,C) を作ろう。 答え ⇒
優勝者、第2位、第3位の3名が表彰台に立つことができる。 開催国と表彰台に立った人の関係を表す規則 gpx_top3(C,L) を作ろう。 ここで、L はその3者の名前のリストとする。たとえば、 gpx_top3(france,[rai,mas,ham]) という関係である。 答え ⇒
member(X,L) は、リストLの中にXが存在することを表す。メンバーは次のとおり定義される。
member(X,[X|_]). member(X,[_|L]) :- member(X,L). |
再帰的な定義になっている。最初の行は、X がリストの先頭に存在することを表わす。2行目は、X がリストの2番目以降に存在することを表す。
scheme の member では、リストの中に指定要素を見つけると、それ以降の要素から成るリストを返り値としていた。リスト操作において、この返り値の得られることのほうが便利なことがある。
そこで、指定要素の次の要素から成るリストを返す member を作ろう。なお、Prolog では引数の数の異なる規則や事実は別ものとして扱われる。
member(X,[X|R],R). member(X,[_|L],R):-member(X,L,R). |
次のとおり動作する。
?- member(c,[a,b,c,d,e],X). X = [d,e] |
また、トレースモードで実行してみよう。具体的には次の手順をとる。
R に何が入ったのか、観察しよう。
開催国 C と入賞者 P (第1位から第8位の人)の関係を表す規則 got_point_in(P,C)を、member を使って作ろう。 答え ⇒
上記の例題のプログラムが利用可能であるとする。
小レポートには、プログラム、質問方法、結果を記載せよ。