给出的错误确实有原因。:)
=\=/2
是一个算术运算符,用于比较两个算术表达式的值是否相等,如果它们不相等,它会产生成功 (true)。如果您尝试在非数字术语上使用它,它将产生错误。
如果要检查术语是否不相同,可以使用\==
. 例如,
?- a \== b.
true.
?- X \== a.
true.
如果您想检查“不可统一”,您将使用\=
:
?- a \= b.
true.
?- X \= a. % X could be unified with 'a' to make them equal
false.
这本身将使您的谓词起作用,尽管它确实不止一次地找到了解决方案:
?- remove_repeats([a,b,b,c,c,c,c,c,d], Result).
Result = [a, b, c, d] ;
Result = [a, b, c, d] ;
false.
?-
尽管逻辑本身没有错误,但可以进行一些清理工作。
remove_repeats([], []).
remove_repeats([X], [X]).
remove_repeats([X,X], [X]).
remove_repeats([X,Y], [X,Y]) :- X \= Y.
remove_repeats([H,H|T], R) :- remove_repeats([H|T], R).
remove_repeats([H1,H2|T], R) :-
H1 \= H2,
remove_repeats([H2|T], Z),
R = [H1|Z].
该子句remove_repeats([X,X], [X]).
是多余的,因为它已经被处理remove_repeats([H,H|T], R) ...
了remove_repeats([X], [X])
。此外,该子句remove_repeats([X,Y], [X,Y]) :- X \= Y.
也是多余的,因为它将由remove_repeats([H1,H2|T], R) ...
and处理remove_repeats([X], [X]).
。R
然后我们可以通过在子句的头部包含统一来整理最后一个子句:
remove_repeats([], []).
remove_repeats([X], [X]).
remove_repeats([H,H|T], R) :- remove_repeats([H|T], R).
remove_repeats([H1,H2|T], [H1|Z]) :-
H1 \= H2,
remove_repeats([H2|T], Z).
摆脱冗余规则也摆脱了冗余结果,因为解决方案不会有不止一种方法可以满足规则:
?- remove_repeats([a,b,b,c,c,c,c,c,d], Result).
Result = [a, b, c, d] ;
false.
?-
编辑
正如@false 在他的评论中指出的那样,如果您使用的是 SWI Prolog,那么您可以使用dif/2
谓词来代替=\=/2
. 所以上面H1 \= H2
是dif(H1, H2)
.