我刚刚开始尝试Prolog,我试图编写一个规则来确定列表是否只包含唯一元素 . 我让它在第二个变体中工作(通过否定正面测试),但我完全不理解为什么第一个变体不起作用 .
鉴于此文件:
uniqueElements([X|Y]) :-
notmember(X, Y),
uniqueElements(Y).
notmember(X, Y) :-
\+ member(X, Y).
hasRepeatedElements([X|Y]) :-
(
member(X, Y) ->
true
; hasRepeatedElements(Y)
).
uniqueElements_2(X) :-
\+ hasRepeatedElements(X).
GNU Prolog解释器给出了以下响应:
| ?- uniqueElements([1,2,3]).
no
| ?- uniqueElements([1,2,3,2,3]).
no
| ?- uniqueElements_2([1,2,3]).
yes
| ?- uniqueElements_2([1,2,3,2,3]).
no
为什么第一个回答“不”? (我希望成员返回false,否定为true,因此在uniqueElements的每次迭代中都不会返回true) . 我想我希望''表现得像'!'在C if子句中,或在Python中的'not'关键字 . 这是误会吗?
1 回答
在
uniqueElements
中,您没有为递归提供基本案例:如果没有该子句,当特定的调用链到达空列表的情况时,它不会找到任何适用的子句,这意味着Prolog中的
fail
. 含义,"unprovable" . 因此,您的调用uniqueElements([1,2,3])
已生成相当于true && true && true && false
的内容 .现在它应该工作 .
hasRepeatedElements
也没有为基本案例定义的子句,但是它未能找到空列表中是否有重复的元素[]
与其语义一致 - 它应该发现空列表中没有重复的元素,第一名 .在Prolog中,“不”意味着“无法证明......” .