您需要定义另一个充当传递关系的谓词。下面的代码同样可以正常工作(注意谓词progenyt,它是实际的传递关系)。
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).
progenyt(X, Y) :- progeny(X, Y).
progenyt(X, Y) :- progeny(X, Z), progenyt(Z, Y).
澄清
当您编写 progeny(X, Y) :- progeny(X, Z), progeny(Z, Y). 时,您会在某个时候让 prolog 尝试匹配 progeny(dexter, Y) :- progeny(dexter, lisa), progeny(lisa, Y).,这就是 prolog 变得“混乱”的时刻。
也就是说,它将尝试将progeny(lisa, Y) 与某些事实相匹配,这对于所有条目都将失败。然后,prolog 将尝试规则progeny(lisa, Y) :- progeny(lisa, Z), progeny(Z, Y).,它要求评估progeny(lisa, Z)。这里你会遇到堆栈溢出,因为progeny(lisa, Y) 要成功,progeny(lisa, Z) 也必须成功,这会导致某种无限循环,这就是为什么你的查询永远不会终止的原因。
在我发布的解决方案中,这永远不会发生,因为progenyt(lisa, Y) 要成功,progeny(lisa, Z) 必须成功,而这永远不会发生(所有事实都失败了)。因此,它只会产生这三个结果,然后会立即终止。
请注意,如果progeny 和progenyt 在最后一行交换,查询也会遇到与之前相同的问题(progenyt(lisa, Y) 要成功,progenyt(lisa, Z) 也必须成功首先,会导致无限循环)。