2011-05-01 75 views
1

例如..Prolog的变量名

insert(X,Ys,[X|Ys]). 
insert(X,[Y|Ys],[Y|Zs]) :- insert(X,Ys,Zs) 

为什么使用ZS作为变量..基本情况显然是简单.. X :: YS的头。 但递归声明将成为第一个目标的延续。你可以第二次获得[b,a,c] 你得到[b,c, 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] ; 

是否继续开始在recusive电话吗?这意味着第一个目标在基本情况下结束了..所以我们下一次开始递归?我也可以看到L开始使用不同的变量位置(又名_G522 vs _G595)。

回答

1

Zs是将X插入Ys的结果。

在Prolog中,你通常不会说延续,但选择点。当insert(a,[b,c],L)已经返回了第一个结果,你开始回溯,Prolog的编译器可以追溯到成调用链找到最后的选择点:

  • 最后一次操作是insert的第一句话的执行,这是确定的并绑定L;
  • 在此之前,最后一个操作是在两个子句之间进行选择,这是一个选择点。

由于在这个选择点,选择第一个子句,第二个子句选择回溯,导致Zs被绑定在谓词中。 L通过从第一个子句回溯而解除绑定,并在第二个选项返回时重新绑定。

0

在Prolog中没有延续,但内置了回溯。

说实话,我花了一些时间来了解该计划。

事情是,Prolog严重依赖于模式匹配,并且当有多个匹配的模式时插入choicepoints。如果你需要一个确定性的程序(即没有选择点),你必须确保一次只有一个模式匹配(这是推荐的方式),或者不希望的执行路径在某处失败(这意味着你丢弃了在这里完成的所有计算路径)。确保一个选择点的最简单方法是使用切割运算符(!/ 0)。

“程序中Zs的实际技术定义是什么?”

在Prolog中,您不必声明变量,它们可以在任何地方引入,并且它们绑定的位置(获取实际值,这是不可变的)有时很难遵循。如果没有第一个谓词,那么第二个列表中总是会有一个未绑定的变量,但是在递归调用之后,该变量在第一个谓词中与[X | YS]统一时会被绑定。由于第一个谓词不包含正文,程序将终止并为用户提供解决方案。正如你所看到的,你的程序不能在第二个谓词中终止,只能在第一个谓词中完成,但从递归函数来说这并不令人惊讶,只需考虑经典因子示例即可。

factorial(0,1). 

factorial(N,F) :- 
    N>0, 
    N1 is N-1, 
    factorial(N1,F1), 
    F is N * F1.