我正在开始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
我对这种运作方式的理解是否正确?或者,我的命令性思维是否有更好的方式来思考/表达上面发生的事情?
答案 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,[ ])
来说服自己。