例如..
insert(X,Ys,[X|Ys]).
insert(X,[Y|Ys],[Y|Zs]) :- insert(X,Ys,Zs)
为什么使用Zs作为变量..基本情况显然很简单.. X :: YS的头部。 但递归声明将是第一个目标的延续。
所以对于插入(a,[b,c],L)你得到L = [a,b,c] 你第二次得到[b,a,c] 第三次得到[b,c,a]
但是程序中Zs的实际技术定义是什么?
[trace] 1 ?- insert(a,[b,c],L).
Call: (6) insert(a, [b, c], _G522) ? creep
Exit: (6) insert(a, [b, c], [a, b, c]) ? creep
L = [a, b, c] ;
Redo: (6) insert(a, [b, c], _G522) ? creep
Call: (7) insert(a, [c], _G595) ? creep
Exit: (7) insert(a, [c], [a, c]) ? creep
Exit: (6) insert(a, [b, c], [b, a, c]) ? creep
L = [b, a, c] ;
继续是否在重复呼叫时开始?意味着第一个目标结束@基本情况..所以我们下次开始@递归?此外,我可以看到开始使用L的不同变量位置(又名_G522 vs _G595)。
答案 0 :(得分:1)
Zs
是将X
插入Ys
。
在Prolog中,您通常不会谈到延续,而是选择点。当insert(a,[b,c],L)
返回其第一个结果并开始回溯时,Prolog编译器会返回到调用链中以查找最后一个选择点:
insert
的第一个子句,该子句是确定性的并绑定L
; 因为在这个选择点,选择了第一个子句,所以在回溯时选择第二个子句,导致Zs
绑定在谓词中。 L
通过从第一个子句回溯而未绑定,并在第二个选项返回时重新绑定。
答案 1 :(得分:0)
Prolog没有延续,但内置了回溯。
说实话,我花了一些时间来理解这个程序。
问题在于Prolog严重依赖于模式匹配,并且当存在多个匹配模式时会插入选择点。如果你想要一个确定性的程序(即没有选择点),你必须确保一次只有一个模式匹配(这是推荐的方式),或者不希望的执行路径在某处失败(这意味着你扔掉了在这里完成的所有计算)路径)。确保一个选择点的最简单方法是使用cut运算符(!/ 0)。
“程序中Zs的实际技术定义是什么?”
在Prolog中,您不必声明变量,它们可以在任何地方引入,并且它们被绑定的地方(获得实际值,这是不可变的)有时很难遵循。如果没有第一个谓词,那么在第二个列表和第二个列表中总会有一个未绑定的变量,但是当在递归调用之后与第一个谓词中的[X | YS]统一时,该变量会被绑定。由于第一个谓词不包含正文,程序终止,并为用户提供解决方案。如你所见,你的程序不能在第二个谓词中终止,只能在第一个谓词中终止,但从递归函数来看并不奇怪,只需要考虑经典的因子示例。
factorial(0,1).
factorial(N,F) :-
N>0,
N1 is N-1,
factorial(N1,F1),
F is N * F1.