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

发布于 2024-11-16 18:04:19 字数 1250 浏览 3 评论 0原文

以下代码是一个 DCG,用于替换 Request 中所有出现的 FindReplace 。将答案放入 Result 中。感谢 mat 在这个问题。

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).

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

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([], []).

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

The following code is a DCG to replace all occurences of Find w/ Replace in Request & put the answer in Result. Thanks to mat, for the code, in this question.

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).

In SWI-Prolog, this expands to the following.

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([], []).

Is this code tail-recursive? There is a call to phrase after the recursive call to replace in the 2nd definition of the predicate replace. There's also E=[F|G] after the recursive call to replace in the 3rd definition of replace. I thought that, if the recursive calls were made last, the code would be tail-recursive. If the generated code isn't tail-recursive, is there any way to get Prolog to generate tail-recursive code? Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瘫痪情歌 2024-11-23 18:04:19

上面的代码包含相当复杂的构造,例如半上下文的非常深远的概括。请注意,上面的 FindReplace 都可以是一般的非终结符 - 不仅仅是列表。

因此,让我们考虑一个更简单的情况:

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

它在许多 Prolog 中扩展为:

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

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

Above code contains quite complex constructs like a very far reaching generalization of a semicontext. Please note that above, both Find and Replace can be general non-terminals - not only lists.

So let's consider a simpler case:

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

which expands in many Prologs to:

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

This isn't tail recursive either, but it can be made to be so by exchanging the two goals.
Still, many consider above translation preferable, since it obviously retains certain desirable properties and also leads to a frequently more efficient execution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文