这个代码是通过扩展Prolog DCG尾递归而生成的吗?

时间:2011-06-21 16:37:14

标签: prolog dcg

以下代码是一个DCG,用于替换FindReplace中所有Request w / Result的出现。把答案放在eos([], []). replace(_, _) --> call(eos), !. replace(Find, Replace), Replace --> Find, !, replace(Find, Replace). replace(Find, Replace), [C] --> [C], replace(Find, Replace). substitute(Find, Replace, Request, Result):- phrase(replace(Find, Replace), Request, Result). 。感谢mat,代码,this question

replace(_, _, A, B) :-
        call(eos, A, C), !,
        B=C.
replace(A, D, B, F) :-
        phrase(A, B, C), !,
        E=C,
        replace(A, D, E, G),
        phrase(D, F, G).
replace(B, C, A, E) :-
        A=[F|D],
        replace(B, C, D, G),
        E=[F|G].

substitute(A, B, C, D) :-
        phrase(replace(A, B), C, D).

eos([], []).

在SWI-Prolog中,这扩展到以下内容。

phrase

这段代码是尾递归的吗?在谓词replace的第二个定义中递归调用replace后,调用E=[F|G]。在replace的第3个定义中递归调用replace之后,还有{{1}}。我认为,如果最后进行递归调用,代码将是尾递归的。如果生成的代码不是尾递归的,有没有办法让Prolog生成尾递归代码?提前谢谢。

1 个答案:

答案 0 :(得分:4)

上面的代码包含非常复杂的结构,例如半导体文本的非常广泛的泛化。请注意,上面FindReplace都可以是一般的非终端 - 不仅仅是列表。

所以让我们考虑一个更简单的案例:

iseq([]) --> [].
iseq([E|Es]) --> iseq(Es), [E].

在许多Prolog中扩展为:

iseq([], Xs, Xs).
iseq([E|Es], Xs0,Xs) :-
   iseq(Es, Xs0,Xs1),
   Xs1 = [E|Xs].

这也不是尾递归,但可以通过交换两个目标来实现。 尽管如此,许多人认为上述翻译更为可取,因为它显然保留了某些理想的属性,并且还导致了更高效的执行。