2014-02-27 91 views
1

我学习的Prolog自己和最近的递归在一张票据传来: -削减在序言

例:第n/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中使用跟踪功能,我发现,这些2个码的调用序列是完全相同的。

我应该把!标记如下?

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

回答

2

第二子句中的切口,因为没有更多的条款和目标之前它(is/2呼叫)是确定性是多余的。我也不认为剪切对尾递归优化起作用(这基本上要求递归调用是子句体中的最后一个目标)。

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

+0

是的,我可以看到,在'第(+,+,+)'削减在第一个声明是没用的。这是我编码解决问题的方法:'nth([X | _],0,X)。 (N,0),N是N-1,第n个(L,N1,X)。 – Pingu

+0

基本上我只是加了约束'N> 0',正确? – Pingu

+0

是的。一个很好的后续练习将试图定义一个适用于任何模式的“n/3”谓词。顺便说一下,这个功能通常在库中使用名字'nth0/3'(从0开始计数)和'nth1/3(从1开始计数)“提供。如果您从零开始计数或从一开始计数,则不建议使用名称“nth/3”以避免含糊不清。 –