首页 文章

削减Prolog的递归

提问于
浏览
1

我自己在学习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 回答

  • 2

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

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

相关问题