Prolog 中递归谓词末尾的剪切

发布于 2024-08-03 06:30:00 字数 464 浏览 6 评论 0原文

pred(Args).
pred(Args) :-
    goalA,
    goalB,
    !,
    pred(Args).
pred(Args) :-
    goalC,
    goalD,
    !,
    pred(Args).

通常我会编写一个与内存性能相关的递归谓词,类似于上面的代码片段。使用剪切来尝试强制进行尾部调用优化。我最近浏览了一个大型的 prolog 代码库,并发现了一些示例,其中剪切实际上是在递归调用之后而不是紧接在递归调用之前。据推测,这会阻止尾调用优化的发生,而不是帮助它。

我的问题是我可以将递归调用之后的剪切移到递归调用之前,而不影响程序的含义吗?这是假设谓词的每个子句的相同相对位置都有一个切口。

现在我又想了一些,我想也许答案是“不一定”,但是在调用之前用剪切重写了所有代码并发现测试套件仍然通过,我也想知道是否还有其他深奥的原因来编写这样的谓词。或者只是糟糕的编码?

pred(Args).
pred(Args) :-
    goalA,
    goalB,
    !,
    pred(Args).
pred(Args) :-
    goalC,
    goalD,
    !,
    pred(Args).

Normally I would write a recursive predicate that was concerned with memory performance something along the lines of the above snippet of code. With the cut being used to try to force tail call optimization to occur. I have recently been going through a large prolog code base and have found some examples where the cut is actually after the recursive call rather than immediately before it. Presumably this has the effect of preventing tail call optimization from happening rather than assisting it.

My question is can I move the cut from after the recursive call to immediately prior to it without affecting the meaning of the program? This is assuming that there is a cut in the same relative location for each clause of the predicate.

Now I've been thinking about it some more, I'm thinking maybe the answer is "not necessarily", but having rewritten all the code with the cut before the call and finding that the test suite is still passing, I'm also wondering if there might be some other esoteric reason for writing predicates like this. Or is it just bad coding?

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

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

发布评论

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

评论(1

林空鹿饮溪 2024-08-10 06:30:00

我的猜测是,这可能是错误的编码(或误解了作者在做什么)

我这么说是因为我自己也犯过同样的错误:

https://mailbox.iai.uni-bonn.de/mailman/public/swi-prolog/2009/001540。 html

http://xonix.habrahabr.ru/blog/60430/ (警告,俄语)

但是来自 SWI 邮件列表的人确认尾递归代码的正确方法是

head :-
       <guard goals>, !,
       <deterministic stuff>,
       head.
head :-
       ...

My guess is that it might be bad coding (or misunderstanding what author was doing)

I'm saying this, because I, myself, did once the same error:

https://mailbox.iai.uni-bonn.de/mailman/public/swi-prolog/2009/001540.html

http://xonix.habrahabr.ru/blog/60430/ (warning, in russian)

But people from SWI mailing-list confirmed that right way of tail-recursive code is

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