PROLOG:addOne谓词,temp时会发生什么。变量命中基本子句,Prolog如何调用值?

时间:2015-02-22 20:22:24

标签: prolog

我需要一些帮助来理解以下Prolog源代码:

addone([],[]).
addone([H|T],[H1|T1]):-H1 is H + 1, addone(T,T1).

此代码采用给定列表,因此打印出另一个列表,其中每个参数都添加了+1。

如果我追踪它,我不明白这项工作究竟如何:

[trace] 69 ?- addone([1,2,3],X).
   Call: (6) addone([1, 2, 3], _G1196) ? creep
   Call: (7) _G1273 is 1+1 ? creep
   Exit: (7) 2 is 1+1 ? creep
   Call: (7) addone([2, 3], _G1274) ? creep
   Call: (8) _G1279 is 2+1 ? creep
   Exit: (8) 3 is 2+1 ? creep
   Call: (8) addone([3], _G1280) ? creep
   Call: (9) _G1285 is 3+1 ? creep
   Exit: (9) 4 is 3+1 ? creep
   Call: (9) addone([], _G1286) ? creep
   Exit: (9) addone([], []) ? creep
   Exit: (8) addone([3], [4]) ? creep
   Exit: (7) addone([2, 3], [3, 4]) ? creep
   Exit: (6) addone([1, 2, 3], [2, 3, 4]) ? creep
X = [2, 3, 4].

我明白了这一点:

Call: (9) addone([], _G1286) ? creep
   Exit: (9) addone([], []) ? creep

从这里我不明白当我到达基本条款时,Prolog如何回忆它保存的值?

请你解释一下这件事是如何运作的,背后的逻辑是什么?

提前谢谢你,Petar!

1 个答案:

答案 0 :(得分:0)

我想您可能正在寻找的答案是:

当Prolog看到这样定义的谓词时(最简单的例子):

foo([]).
foo([_|_]).

此谓词现在将在适当的列表中具有确定性。换句话说,它只会成功一次。这是因为Prolog可以通过嘲笑这两个条款来识别它们是互斥的。换句话说,对于任何非空列表,第二个子句只能应用,对于空列表,第一个子句只能应用。

换句话说,对于长度 Len 的正确列表,在 Len 调用第二个子句之后,将跟随第一个子句的调用。此时它成功,所有递归调用(尾递归)都将成功,与调用它们的方式相反。

在您的示例中,在进行递归调用之前,会计算一个值,并在调用成功时准备好使用。

这里有一件事是,当你用它调用第二个参数变量时,你将继续用列表的头部(你计算的数字)和一个自由尾[H1|T1]来统一这个变量。传递给递归调用addone(T, T1)。只有当第一个参数是空列表时,第二个参数才会与空列表统一:addone([], [])。现在,在递归调用的返回时,值列表(从后面增长)将与免费尾部[4|[]][3|[4|[]]] [2|[3|[4|[]]]]统一,最终构建最终列表第二个论点。