《Programming In Prolog》的第4.4章节,截断的问题(Problems with the Cut)里,作者讲解了利用截断机制时可能会出的状况。内容很基础,但之前没太留意这个,只是把求解问题就得了,没考虑太多设计之外的情况。书中给出了两个示例:
示例一:将第2个列表附加到第1个列表之后,形成新的列表的代码:
append([], X, X) :- !.
append([A|B], C, [A|D]) :- append(B, C, D).
然后进行3个询问:
?- append([a,b,c],[d,e], X).
?- append([a,b,c], X, Y).
?- append(X, Y, [a,b,c]).
前2个的结果没什么问题,但第3个却出了问题,给出了这样的结果:
X=[], Y=[a,b,c].
它只给出这种情况的结果,因为在第1个参数为空,也能够匹配成功,但后面的截断会使查询就此打住。
示例二:表述人的父母数量,亚当和夏娃例外的代码:
number_of_parents(adam, 0) :- !.
number_of_parents(eve, 0) :- !.
number_of_parents(X, 2).
然后进行3个询问:
?- number_of_parents(eve, X).
?- number_of_parents(john, X).
?- number_of_parents(eve, 2).
前2个的结果没什么问题,但第3个却出了问题,给出了这样的结果:
yes
这个命题应当为假才对。因为前面的语句匹配失败后,直接与number_of_parents(X, 2).语句进行匹配,而这个语句,会对任意第1个变量,都将第2个变量匹配为2。(而且这里解释器给出警告,说这个变量只出现过1次。需要表示任意值的话,用_符号更好一些。)
书里就第2个示例给出了两个解决方案,将代码重写为:
number_of_parents(adam, N) :- !, N = 0.
number_of_parents(eve, N) :- !, N = 0.
number_of_parents(X, 2).
或
number_of_parents(adam, 0).
number_of_parents(eve, 0).
number_of_parents(X, 2) :- \+(X=adam), \+(X=eve).
因此,只有当你对如何使用规则语句有明确的策略时,才能可靠地使用截断。如果你要更改相关规则语句,则必须审查所有使用截断的地方。
示例一:将第2个列表附加到第1个列表之后,形成新的列表的代码:
append([], X, X) :- !.
append([A|B], C, [A|D]) :- append(B, C, D).
然后进行3个询问:
?- append([a,b,c],[d,e], X).
?- append([a,b,c], X, Y).
?- append(X, Y, [a,b,c]).
前2个的结果没什么问题,但第3个却出了问题,给出了这样的结果:
X=[], Y=[a,b,c].
它只给出这种情况的结果,因为在第1个参数为空,也能够匹配成功,但后面的截断会使查询就此打住。
示例二:表述人的父母数量,亚当和夏娃例外的代码:
number_of_parents(adam, 0) :- !.
number_of_parents(eve, 0) :- !.
number_of_parents(X, 2).
然后进行3个询问:
?- number_of_parents(eve, X).
?- number_of_parents(john, X).
?- number_of_parents(eve, 2).
前2个的结果没什么问题,但第3个却出了问题,给出了这样的结果:
yes
这个命题应当为假才对。因为前面的语句匹配失败后,直接与number_of_parents(X, 2).语句进行匹配,而这个语句,会对任意第1个变量,都将第2个变量匹配为2。(而且这里解释器给出警告,说这个变量只出现过1次。需要表示任意值的话,用_符号更好一些。)
书里就第2个示例给出了两个解决方案,将代码重写为:
number_of_parents(adam, N) :- !, N = 0.
number_of_parents(eve, N) :- !, N = 0.
number_of_parents(X, 2).
或
number_of_parents(adam, 0).
number_of_parents(eve, 0).
number_of_parents(X, 2) :- \+(X=adam), \+(X=eve).
因此,只有当你对如何使用规则语句有明确的策略时,才能可靠地使用截断。如果你要更改相关规则语句,则必须审查所有使用截断的地方。