スターブルーが言ったことを少し拡張させてください。
論理的には、このプログラムは、1 番目が冠詞、2 番目が名詞、3 番目が動詞、4 番目が別の冠詞、5 番目が別の名詞である場合、5 つの任意のセットが文であると述べています。Prolog の魔法は、「最初の単語に対してすべての冠詞を試してから、2 番目の単語に対してすべての名詞をループして試す、というように、答えを得る方法を教える必要がないことです」; 代わりに、問題を宣言的に述べるだけで (最初の単語は記事など)、Prolog がそれを理解します。したがって、質問が論理的に述べられている限り、(最終的には) 考えられるすべての有効な回答が得られるはずです。
ただし、Prolog は実際のコンピューター上で実行されるため、答えを見つけるための実際の戦略が必要であり、その戦略は深さ優先探索です。: 各変数を順番にバインドし、その変数を統合できるまであらゆる可能性を試してから、次の変数に移動します。次の解決策を求めると、他の可能性があった最後の統合に戻り、述語を満たす別の解決策を見つけようとします。これが、生成された文が行った順序で出てくる理由です: 単語 5 が最後に統合されるため、Prolog がバックアップするとき、単語 5 を再試行します。単語 5 のすべての可能な統合を使い果たすと、単語 4 に戻り、次に移動します。再び単語 5 に進みます。したがって、最終的には 5 つの単語すべてについてあらゆる可能性を試します。試している順序が気に入らない場合は、変数をバインドする順序を変更できます。たとえば、最初の単語を再試行し、次に 2 番目の単語を再試行する場合は、プログラムを次のように書き直すことができます。
sentence(Word1,Word2,Word3,Word4,Word5) :-
word(noun,Word5),
word(article,Word4),
word(verb,Word3),
word(noun,Word2),
word(article,Word1).
?- sentence(X,Y,Z,Q,A), write([X,Y,Z,Q,A]).
[a,criminal,eats,a,criminal] ;
[every,criminal,eats,a,criminal] ;
[a,big kahuna burger,eats,a,criminal]
ご想像のとおり、これはスタックによって内部的に管理されています。最新のプロローグのほとんどは、WAM (ウォーレン抽象マシン) と呼ばれる手法で実装されています。WAM は、コール スタックがあるという点で他のほとんどのプログラミング言語の仮想マシンと似ていますが、各バインディングで変数をプッシュするトレイルと呼ばれる 2 つ目のスタックもあります。バックトラッキングは、トレイルから最後の変数をポップし、それを統合してそこから再開しようとすることで機能します。この変数に他に統合がない場合は、別の変数をスタックからポップし、さらにバックアップします。Prolog がトレイルを使い果たすと、バインドが不可能なため、単純に false を返します。