削减Prolog的递归

时间:2014-02-27 16:36:44

标签: prolog

我自己在学习Prolog,最近发现了一条笔记: -

  

示例:nth / 3

     
      
  • 例如,要查找列表的第n个元素,我们可以使用
  •   
    nth([X|_],0,X). 

    nth([_|L],N,X) :- N1 is N - 1, nth(L,N1,X).
  
      
  • 列表的第0个元素是列表的头部(第一个子句),否则   我们取列表尾部的第n-1个元素(第二个子句)。

  •   
  • 一旦我们找到了第n个元素,我们就无法通过回溯来找到它。

  •   
 nth([X|_],0,X). 
 nth([_|L],N,X) :- N1 is N - 1, !, nth(L,N1,X). 
  
      
  • 添加切口使其清晰,可能是尾递归所必需的   优化
  •   

然而,当我在Prolog中使用trace函数时,我发现这两段代码的调用序列完全相同。

我应该把!改为标记如下?

 nth([X|_],0,X) :- !. 
 nth([_|L],N,X) :- N1 is N - 1, nth(L,N1,X). 

1 个答案:

答案 0 :(得分:2)

第二个子句中的剪切是多余的,因为没有更多的子句,而它之前的目标(is/2调用)是确定性的。我也不认为剪切在尾递归优化中扮演任何角色(这基本上要求你递归调用是子句体中的最后一个目标)。

但是,在担心削减展示位置之前,您应该检查如果以nth/3以外的模式调用nth(+,+,-)谓词会发生什么。例如,模式nth(+,+,+)中发生了什么,即当你实例化所有参数调用谓词时,元素不在列表中?提示:将剪切移动到第一个子句并不能解决问题。