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

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

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

现在我一直在考虑更多,我在想答案可能是“不一定”,但是在调用之前用 cut 重写了所有代码并发现测试套件仍然通过,我也在想知道编写这样的谓词是否还有其他深奥的原因。或者它只是糟糕的编码?

4

1 回答 1

2

我的猜测是它可能是糟糕的编码(或误解了作者在做什么)

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

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 :-
       ...
于 2009-08-28T23:20:03.080 回答