既存の述語を理解するとき、または新しい述語を設計するときに、Prolog がどのように動作するかを理解するのに役立ちます。次のようなクエリを作成すると、次のようになります。
sum( succ(succ(0)), succ(succ(succ(0))), Answer ).
sum(_, _, _)
Prolog は、一致するファクトとルール( )を探し、一致sum/3
する最初のものを選択します。適用される規則は次のとおりです。
(1) sum( succ(X), Y, succ(Z) ) :- sum( X, Y, Z ).
(2) sum( 0, X, X ).
クエリを見ると、明らかにルール 1 のパターンと一致しています。Prolog では、変数は任意の種類の用語にインスタンス化でき、同じ名前の変数は統合 (同じ値にインスタンス化) されることに注意してください。Prolog がルール #1 の「ヘッド」をクエリと統合する場合、次のように変数を統合することでこれを行います。
X = succ(0)
Y = succ(succ(succ(0)))
(A) Answer = succ(Z)
まだバインドされていない (具体的な値が割り当てられていない)にもかかわらず、Answer
には値があることに注意してください。ここで、クエリになるルールに従います。これはクエリになります。succ(Z)
Z
sum(X, Y, Z)
sum( succ(0), succ(succ(succ(0))), Z )
| | |
X Y Z
これは の新しいクエリであるため、Prolog は再び先頭から開始されますsum/3
。最初と同じように、ルール #1 と次の統合が一致します。
X = 0
Y = succ(succ(succ(0)))
(B) Z = succ(Z')
の head で使用されているものとは異なるため、上記を使用しZ'
て の他の変数と区別しています。これは、C で として宣言された関数があり、どこかから別のローカル変数でそれを呼び出す場合、その名前は 2 つの異なる場所で使用され、2 つの異なる変数を表すようなものです)。Z
sum(succ(0), succ(succ(succ(0))), Z)
Z
sum(..., succ(Z))
int f(x) { return 2*x; }
x
x
次に、次の再帰クエリをたどることができます。これは次のようにsum(X, Y, Z')
なります。
sum( 0, succ(succ(succ(0))), Z' )
| | |
X Y Z'
この再帰クエリは、最初の引数 が一致しないため、ルール 1 に0
一致しませんsucc(X)
。ただし、ルール #2 に一致します。
0 = 0
X = succ(succ(succ(0)))
(C) X = Z'
今X = succ(succ(succ(0)))
そうZ' = succ(succ(succ(0)))
です。このルールにはクエリが含まれていないため、最終的にクエリ元に戻ります。これを上記の (B) に戻すと、次のようになります。
Z = succ(Z') = succ(succ(succ(succ(0))))
これを (A) に戻します。
Answer = succ(Z) = succ(succ(succ(succ(succ(0)))))
そして、あなたはそれを持っています。trace
@CapelliC が言及した機能を使用すると、これらの連続するステップが Prolog インタープリターで発生するのを確認し、変数のインスタンス化をたどることができます。