让我扩展一下starblue所说的内容。
从逻辑上讲,如果第一件事是冠词,第二件事是名词,第三件事是动词,第四件事是另一个冠词,第五件事是另一个名词,那么这个程序说任何五件事都是一个句子。Prolog 的神奇之处在于您不必告诉它如何得到答案,例如“尝试每个文章的第一个单词,然后循环尝试每个名词的第二个单词,等等”;相反,您只需以声明的方式陈述您的问题(第一个词是一篇文章等),Prolog 就会弄清楚。因此,只要您的问题是合乎逻辑的,您就应该(最终)得到所有可能的有效答案。
因为 Prolog 运行在一台实际的计算机上,它必须有一个实际的策略来寻找答案,并且该策略是深度优先搜索:它依次绑定每个变量,尝试每一种可能性,直到它可以统一该变量,然后它移动到下一个变量。当您要求下一个解决方案时,它会备份到具有其他可能性的最后一个统一,并尝试找到另一个满足谓词的统一。这就是为什么生成的句子按照它们的顺序出现:单词 5 最后统一,所以当 Prolog 备份时,它会重试单词 5。当它用尽单词 5 的所有可能的统一时,它会备份到单词 4,然后移动再次前进到第 5 个单词。所以它最终会尝试所有五个单词的所有可能性。如果您不喜欢它尝试的顺序,您可以更改绑定变量的顺序。例如,如果您希望它重试第一个单词,然后重试第二个单词,您可以将程序重写为:
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]
正如您的期望,这是由堆栈内部管理的。大多数现代 Prologs 都是用一种称为 WAM 的技术实现的,即 Warren Abstract Machine。WAM 与大多数其他编程语言虚拟机一样,有一个调用堆栈,但还有一个称为跟踪的第二个堆栈,它在每次绑定时将变量推送到该堆栈上。回溯然后通过将最后一个变量从路径中弹出并尝试统一它并从那里恢复来工作。如果这个变量没有其他统一,它会从堆栈中弹出另一个变量并进一步备份。当 Prolog 用完踪迹时,它只返回 false,因为不可能进行绑定。