2009-08-27 69 views
4
pred(Args). 
pred(Args) :- 
    goalA, 
    goalB, 
    !, 
    pred(Args). 
pred(Args) :- 
    goalC, 
    goalD, 
    !, 
    pred(Args). 

通常我会写一个关于内存性能的递归谓词,它与上面的代码片段相关。切割被用来试图强制尾巴呼叫优化发生。我最近经历了一个大的序言代码库,并且发现了一些例子,其中的切割实际上是在递归调用之后,而不是在它之前。大概这有防止尾部呼叫优化发生而不是协助它的效果。在Prolog中递归谓词的末尾处切割

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

现在我一直在想这件事,我想也许答案是“不一定”,但是在调用之前用切割重写了所有的代码并发现测试套件仍在传递,我也想知道是否可能有其他一些深奥的理由来编写这样的谓词。或者它只是糟糕的编码?

回答

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 :- 
     ... 
+0

由于我移动切割并没有改变代码在所有测试用例中的行为方式,我认为你可能是对的 - 它只是编码不好。 – nedned 2009-08-29 07:01:13