有时引入绿色削减确实有意义——甚至在append/3
,但必须注意,这样的切割仍然是绿色切割。也就是说,削减确实提高了效率(在一定程度上)并且不会影响答案。
引入绿色剪切有一个非常简单的经验法则:如果您在没有任何保护的情况下将剪切添加到纯粹、单调的程序中,那么您可以非常确定它将是红色剪切,从而破坏了程序的含义。
这条经验法则很少有例外。例如,您可以在可变自由目标之后添加剪切,前提是没有进一步的规则等。尝试找出受剪切影响的情况绝对是一个很好的训练。
但回到你的程序append2/3
。目前,即使替代规则确实适用,剪切也总是剪切,在这种情况下,剪切会删除答案,这是我们想要避免的。
那么第一个子句什么时候是唯一相关的呢?
如果第一个参数是[]
, thus append2([], Xs, Ys).
- 但如果最后一个参数是[]
(还有更多更复杂的情况)。让我们用原始的无剪切定义来尝试这两种情况:
?- append([], Ys, Zs).
Ys = Zs.
?- append(Xs, Ys, []).
Xs = Ys, Ys = []
; false.
因此,在第一种情况下,系统能够立即确定存在单一解决方案,同时生成答案。然而,在第二种情况下,Prolog 系统是not确定是否需要另一个答案——可以说它“留下了一个选择点”。遗憾的是,因为确定在这种情况下也只存在一个答案是相当微不足道的。削减是理想的选择,可以提供帮助。但不加防范的割伤弊大于利。
削减可能会削减,前提是第三个参数是[]
:
append3(Xs, Ys, Zs) :-
( Zs == [] -> ! ; true ),
Xs = [],
Ys = Zs.
append3([X|Xs], Ys, [X|Zs]) :-
append3(Xs, Ys, Zs).
如果仅知道第三个参数,则该程序现在更加高效,因为它不会留下任何选择点。
?- append(Xs,Ys,[1]).
Xs = [], Ys = [1]
; Xs = [1], Ys = []
; false.
?- append3(Xs,Ys,[1]).
Xs = [], Ys = [1]
; Xs = [1], Ys = [].
该程序不一定更快,因为测试本身可能很昂贵。理想情况下,Prolog 系统能够在内部完成此类操作,但有时程序员必须提供一些帮助。