PROLOG:addOne 谓词,当 temp 时会发生什么。变量命中基本子句,Prolog 如何调用值?
PROLOG: addOne predicate, what happens when temp. variable hits the base clause, how does Prolog call values?
我需要一些帮助来理解以下 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!
我想您可能正在寻找的答案是:
当 Prolog 看到这样定义的谓词时(最简单的例子):
foo([]).
foo([_|_]).
这个谓词现在在适当的列表上是确定性的。换句话说,它只会成功一次。这是因为 Prolog 可以通过查看这两个子句来识别它们是互斥的。换句话说,对于任何非空列表只能应用第二个子句,对于空列表只能应用第一个子句。
换句话说,对于长度为 Len 的适当列表,在 Len 调用第二个子句后,调用第一个子句条款将遵循。到那时它会成功,并且所有递归调用(尾递归)都将成功,顺序与调用顺序相反。
在您的示例中,甚至在进行递归调用之前,都会计算一个值并准备好在调用成功时使用。
这里的一件事是,当你用它调用第二个参数一个变量时,你将继续将该变量与列表的头部(你计算的数字)和一个空闲的尾部统一起来[H1|T1]
,您将其传递给递归调用 addone(T, T1)
。只有当第一个参数是空列表时,第二个参数才会统一为空列表:addone([], [])
。现在,在递归调用的 return 上,值列表(从后面增长)将与自由尾部 [4|[]]
、[3|[4|[]]]
[2|[3|[4|[]]]]
统一,最终构建第二个参数中的最终列表。
我需要一些帮助来理解以下 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!
我想您可能正在寻找的答案是:
当 Prolog 看到这样定义的谓词时(最简单的例子):
foo([]).
foo([_|_]).
这个谓词现在在适当的列表上是确定性的。换句话说,它只会成功一次。这是因为 Prolog 可以通过查看这两个子句来识别它们是互斥的。换句话说,对于任何非空列表只能应用第二个子句,对于空列表只能应用第一个子句。
换句话说,对于长度为 Len 的适当列表,在 Len 调用第二个子句后,调用第一个子句条款将遵循。到那时它会成功,并且所有递归调用(尾递归)都将成功,顺序与调用顺序相反。
在您的示例中,甚至在进行递归调用之前,都会计算一个值并准备好在调用成功时使用。
这里的一件事是,当你用它调用第二个参数一个变量时,你将继续将该变量与列表的头部(你计算的数字)和一个空闲的尾部统一起来[H1|T1]
,您将其传递给递归调用 addone(T, T1)
。只有当第一个参数是空列表时,第二个参数才会统一为空列表:addone([], [])
。现在,在递归调用的 return 上,值列表(从后面增长)将与自由尾部 [4|[]]
、[3|[4|[]]]
[2|[3|[4|[]]]]
统一,最终构建第二个参数中的最终列表。