2

我在 Prolog 中做一个非常简单的练习,跟踪中有一些我不明白的东西。>该程序是对表示为后继的整数的“大于”( ):

greater_than(succ(_), 0).
greater_than(succ(A), succ(B)) :-
  greater_than(A, B).

我的问题:我不明白为什么请求会在以下跟踪中greater_than(succ(succ(succ(0))),succ(0))生成:redo

[trace] ?- greater_than(succ(succ(succ(0))),succ(0)).
Call: (6) greater_than(succ(succ(succ(0))), succ(0)) ? creep
Call: (7) greater_than(succ(succ(0)), 0) ? creep
Exit: (7) greater_than(succ(succ(0)), 0) ? creep
Exit: (6) greater_than(succ(succ(succ(0))), succ(0)) ? creep
true ;
Redo: (7) greater_than(succ(succ(0)), 0) ? creep
Fail: (7) greater_than(succ(succ(0)), 0) ? creep
Fail: (6) greater_than(succ(succ(succ(0))), succ(0)) ? creep
false. 

为什么redo这里有?我怎样才能避免它(当然没有削减)?

顺便说一句,在你问之前:不,这不是某种家庭作业......

4

2 回答 2

2

好的,所以这是一个给定的编译器/版本组合可能有也可能没有的编译器优化。

更高版本的 SWI 没有这个问题。它可能与子句索引有关。这种行为会出现在没有索引的实现上,或者只有第一个参数上的索引。

但显然,“SWI-Prolog 提供了对多个参数的“即时”索引”。SWI 5.6.56 手册指出“最多可以索引 4 个参数”。所以它可能索引不止一个。

于 2012-08-30T09:30:00.173 回答
0

有一个重做的原因是,如果按照下一个子句,prolog 不能推断(不检查它),那么会有一个替代解决方案。诚然,在这种情况下,它只是一个头部统一检查(并不是说这总是微不足道的),但它可能需要很长时间(甚至永远不会终止)。

现在,这正是您应该使用 cut 的地方:您知道额外的选择点不会产生解决方案(因此您不会更改语义 - 绿色剪切)。或者(但它主要是覆盖剪切的语法糖)您可以使用 if-then-else:

greater_than(succ(A), B):-
    B = succ(BI) ->
    greater_than(A,BI)
    ; B = 0.

并不是说这仍然会进行额外的计算,而 cut 可以避免这些计算。

PS:我怀疑有人会认为这是作业XD

于 2012-08-30T08:53:52.787 回答