好的,所以我有一些代码可以连接两个列表。代码完全没问题,只是我努力理解代码是如何工作的。
以下是代码:
conc([],L,L).
conc([H|L1],L2,[H|L3]):-
conc(L1,L2,L3).
假设我们有2个列表:[3,4,2]和[9,9]我想连接。
Step 1:
H = 3
L2 = [9, 9]
L1 = 4,2
Step 2:
L2 = [9, 9]
H = 4
L1 = [2]
Step 3:
L2 = [9, 9]
H = 2
L1 = []
Step 4:
L = [9,9] .... Now why does it not just fail? In my brain [9,9] is not equal to [3, 4, 2]
Step 5:
L2 = L3 = [9, 9]
H = 2
L1 = []
Step 6:
L2 = [9, 9]
H = 4
L1 = [2]
L3 = [2, 9, 9]
Step 7:
L2 = [9, 9]
H = 3
L1 = [4, 2]
L3 = [4, 2, 9, 9] And done
我发现什么令人困惑?我一定是在看这个错误,L2也只是在递归调用中保持静态,所以我不明白我们通过将第一个输入移动到第三个来实现了什么?
答案 0 :(得分:2)
在您的第4步中,您没有统一[3, 4, 2]
和[9, 9]
;您正在使用自由变量统一[9, 9]
。
您是正确的,步骤3中的绑定是L2 = [9, 9]
,H = 2
和L1 = []
。请注意L3
未绑定!递归调用是conc(L1, L2, L3)
,因此conc([], [9, 9], L3)
。此目标将与conc
的第一个子句统一,引入新的绑定L3 = [9, 9]
。这是由conc([], L, L)
条款引起的,它强制L3
与L
绑定的任何内容统一,在此调用中只有[9, 9]
。
然后,如您所述,评估将继续进行第5步。
您的Prolog可能有一个可以帮助您理解这一点的示踪剂。在SWI-Prolog中,conc
目标看起来像这样(_Gxxxx
是自由变量):
?- trace, conc([a,b], [c,d], Xs).
Call: (7) conc([a, b], [c, d], _G2467) ? creep
Call: (8) conc([b], [c, d], _G2590) ? creep
Call: (9) conc([], [c, d], _G2593) ? creep
Exit: (9) conc([], [c, d], [c, d]) ? creep
Exit: (8) conc([b], [c, d], [b, c, d]) ? creep
Exit: (7) conc([a, b], [c, d], [a, b, c, d]) ? creep
Xs = [a, b, c, d].
请注意,输入第三个Call
时,变量作为第三个参数,Exit
s,该变量绑定到列表。