了解Prolog中的递归规则

时间:2014-05-26 04:27:32

标签: recursion prolog

我正在开始Prolog,由Seven Langauges in Seven Weeks提供,并且在理解prolog如何处理递归方面有点挣扎。

给出以下代码:

sum(0, []).
sum(Total, [Head|Tail]) :- sum(Sum,Tail), Total is Head + Sum.

% executed in the Prolog interpreter:
sum(X, [1,2,3])
X = 6

我理解这段代码在做什么,但我对Prolog如何解析sum的递归调用感到有些不知所措。主要是,我很奇怪sum内没有明确的“回报”。

我的理解是这样的事情发生了:

:一种。口译员试图通过调用总和来统一规则总和(X,[1,2,3]):

0 Sum(X, [1, 2, 3])
1 Sum(Y, [2,3] 
2 Sum(Z, [3])
3 Sum(0, []) % our recursive base

B中。一旦我们达到基本事实,它就会爬上递归的“堆栈”:

3 Sum(0, []), Total = 0 % we start at our base fact
2 Sum(1, [3]), Total = 3
1 Sum(2, [2, 3]), Total = 5 
0 Sum(X, [1, 2, 3]) Total = 6 % sweet, sweet unification

我对这种运作方式的理解是否正确?或者,我的命令性思维是否有更好的方式来思考/表达上面发生的事情?

2 个答案:

答案 0 :(得分:3)

是的,你的想法是正确的。我会略微改写你所说的内容,以便它可能更清晰一些。

要理解Prolog执行的第一件事就是要意识到Prolog就像一个弱定理证明者。它会尝试使您的查询成立。因此,当您输入查询?- sum(X, [1,2,3]).时,Prolog将尽力使其成为现实。在这种情况下,正如我们所看到的,它需要将X绑定到6,让我们看看如何。

你给Prolog证明sum(X, [1, 2, 3])为真的唯一元素是

sum(0, []).

sum(Total, [Head|Tail]) :- sum(Sum,Tail), Total is Head + Sum.

很明显,Prolog对第一个条款无能为力,因为它无法统一[][1, 2, 3]。所以它试图通过使用第二个子句来证明你的查询。

然后会发生的是,它会尝试按顺序证明sum(Sum,Tail)Total is Head + Sum。证明这两个选项中的第一个将导致递归调用,最终将使用Tail = []调用它。此时,Prolog将使用您提供的第一个子句,并推断出Sum因此0。它现在将具有在递归的最后一步证明第二部分(Total is Head + Sum)的元素。然后,正如您猜测的那样,递归会回溯到初始谓词。

答案 1 :(得分:1)

这是对的。显式“返回”的作用是通过满足定义sum/2的谓词中空列表总和的独特方式来实现的。

您可以通过在翻译处执行目标sum(X,[ ])来说服自己。