太多的回溯:为什么出现“重做”在这里?(Too much backtracking: why is

2019-07-31 06:25发布

我做的序言中一个非常简单的练习,有件事情我不跟踪了解。 该程序是一个“大于”( > )上表示为接班人整数:

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吗? 我怎样才能避免它(无切口,当然)?

顺便说一句,我可以告诉大家:不,这不是什么功课?

Answer 1:

OK,所以这是一个给定的编译器/版本组合可能会或可能不会有一个编译器优化。

SWI的版本不再有这个问题。 这可能与条款索引 。 这种行为将在实施中可以看到没有索引,或者使得只有指数的第一个参数。

但很显然, “SWI-Prolog的提供`刚刚在时间”在多个参数索引” 。 SWI 56年6月5日手动声明说:“最多4个参数可以被索引”。 这大概索引不止一个。



Answer 2:

有原因有重做是序言不能推断出(不检查的话),如果,按照下一项,将有一个替代解决方案。 诚然,在这种情况下,只有一个头统一检查(不,这始终是微不足道的),但它可能是东西,可能需要很多时间(甚至从来没有终止)。

现在,这是什么地方你应该使用斩:你知道,多一个选择点不会产生解决方案(这样你就不会改变语义 - 绿色切)。 或者(但它主要是语法糖覆盖切口),可以使用IF-THEN-ELSE:

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

不,这仍然没有这将与切避免额外的计算。

PS:我怀疑有人会认为这是功课XD



文章来源: Too much backtracking: why is there a “redo” here?