Prologプログラミングの構文
磯野家の家族関係でPrologプログラミングを体験しました。これまでは、とにかく動かす、どのように動くか考える、ということをやってきました。
ここからはプログラムの構文について、もう少し詳しいことをみていきましょう。
4.1データ
Prologの動作の仕方はCなどの手続き型の言語とは大分違います。先ず、基本的なデータとして、定数と変数を考えましょう。
4.1.1 定数
Prologで用いる数には整数と実数があります。通常、扱える数の範囲というのは処理系によって異なりますから、一概には言えませんが、一般に -16383から16383までの数が扱えるようになっています。
実数も使えますが、典型的なPrologプログラムでは実数はあまり使いません。Prologは非数値的な記号計算向きの言語ですので、項目の数を数えるといったような場合に整数はよく使われますが、実数の必要性はあまりありません。
文字定数では、英字(大文字・小文字)、数字、アンダーラインが使えますが、普通は英小文字で始めます。
toro anago2 ikura_04 hotate_1_2
大文字で始まる文字定数を使いたい場合は、シングルクォーテーションで括ります。
'Ama_Ebi' 'Chu_Toro' 'Negi_Toro'
4.1.2 変数
変数の名称は英字(大文字・小文字)、数字、アンダーラインが使えます。英大文字またはアンダーラインで始めます。
X Result Object2 List_01 _dosV _1234
一般的な変数は英大文字で始めます。そのプログラムで特殊な働きをする変数はアンダーラインで始めたりします。実際には上の例で_1234は、何を行う変数かよく判りませんから、変数名としては良くない例です。プログラムはできるだけ判りやすいように、変数名もその変数の働きを表したものにすべきです。
変数が節の中に1度しか現れず、その変数が特に重要ではない場合、アンダーライン1文字のみの無名変数を使います。
hasachild(X):-parent(X,Y).
という節の場合、変数Yには特に意味はありません。そこで、
hasachild(X):-parent(X,_).
のように記述するのが一般的です。これをプログラムに追加して実行してみましょう。どうでしょうか、無名変数に関しても答えを表示しましたね。これでは、無名変数も普通の変数も変わりません。では、どうして無名変数を使うのでしょうか。
これは、実は専ら「プログラムを読む人のため」です。他人のプログラムは判りにくいものです。そこで、「この変数は特に重要な意味はないよ」ということを、はっきり示すために無名変数を使うのです。
しかし、次のような場合、注意が必要です。
somebody_has_child :- parent(_,_).
これは、誰かが誰かの親であるという記述があれば、子供のいる人がいるということができる、ということです。これは、次と等価です。
somebody_has_child :- parent(X,Y).
そして、これは次とは全く異なります。
somebody_has_child :- parent(X,X).
1つの節の中に無名変数を2つ以上書いても、その無名変数はそれぞれ異なったものとして扱われます。しかし、一般の変数は同じ値を持ったものとして扱われるのです。つまり、もし、
somebody_has_child :- parent(X,X).
とした場合は、
parent(sazae,sazae).
のような、親と子が同一の組み合わせが存在すればyes、存在しなければnoと答えるようになります。parent節の定義からいって、これでは常にnoになってしまいますね。
同一の変数が同一の値を持ったものとして扱われるのは同じ節の中だけです。例えば、
descendant(X,Y):- % descendant_rule_1
parent(Y,X).
descendant(X,Y):- % descendant_rule_2
parent(Y,Z),
descendant(X,Z).
では、最初の節のX、Zと2番目の節のX、Zとはそれぞれ異なる変数でした。このような点はCなどとは大きく異なりますから、注意が必要です。
4.1.3 構造
複数の成分を持ったデータを構造データ、または単に構造(structure)と呼びます。例えば、
date(1996,may,1).
は、年、月、日という3つの要素を成分として持った構造です。カッコの前の名称を関数子(functor)と言います。カッコの中は引数です。最初に扱った
parent(namihei,sazae).
もまた、構造なのです。
先の例では全ての成分が定数でしたが、勿論、変数を扱うこともできます。
date(1996,may,Day).
このように記述すると、1996年5月の任意の日を表すこととなります。Dayは変数で、実行時に何らかの値を設定されるのです。
成分として構造を扱うこともできます。
triangle(point(4,2),point(6,4),point(7,1)).
また、同一の関数子で引数の数を変えることもできます。
point(X,Y).
point(X,Y,Z).
Prologでは、同じ名称の関数子で引数の数の異なるものをそれぞれ定義することができます。これは、Prologの関数子はその名称とアリティ(arity)(引数の数)で一意に決まっているためです。引数が2つのpointと3つのpointとは、別の構造だとPrologは思っているのです。
Prologのデータ(定数、変数、構造)を総称して項(term)と言います。
《演習問題》
- 次のものは項として正しいか。また、定数、変数、構造のいずれか。
- Shirayaki
- shirayaki
- 'Shirayaki'
- _shirayaki
- 'Yoshida likes shirayaki'
- likes(yoshida,shirayaki)
- 12
- 3(X,Y)
- likes(chikuyoutei(shirayaki))
- 長方形、正方形、円をPrologの構造として表現する方法を考えなさい。その際、できるだけ効率の良い方法を考えること。
4.2 マッチング/ユニファイ
いままで何回かPrologの動き方を考えてきました。ある質問を入力された場合、Prologは先ず、同一の節があるかどうかを探します。なければ、同じ関数子の節があるかどうかを探します。その際、変数があればその変数に適当な値を設定します。例えば、
?- date(1996,Month,Day).
と入力した場合、プログラム中に
date(1996,5,5).
という記述があれば、PrologはDayに5、Monthに5という値をそれぞれ設定します。このような操作を一致させる、という意味でマッチング(matching)と言います。また、変数に適当な値を代入して、2つの節を同じ形にする、という意味でユニファイ(unify)とも言います。その結果として、Prologは
Day = 5
Month = 5
という出力をします。
《演習問題》
次のユニファイは成功するか。もし、成功するならば、その結果として変数に設定される値を答えなさい。
- point(A,B)とpoint(1,2)
- point(A,B)とpoint(X,Y,Z)
- plus(2,2)と4
- triangle(point(-1,0),P2,P3)とtriangle(P1,point(1,0),point(0,Y))
目次に戻る