H\==Elem tests syntactic inequality at the point in time when the target is executed. But later joining can make the variables the same:
?- H\==Elem, H = Elem. H = Elem. ?- H\==Elem, H = Elem, H\==Elem. false.
So, here we check whether they are (syntactically) different, and then they are all unified and, therefore, no longer different from each other. So this is just a temporary test.
The goal of member(Elem, T) , on the other hand, is true if Elem is actually an element of T Consider:
?- member(Elem, [X]). Elem = X.
What can be read as
(When) does that Elem is an element of the list [X] ?
and the answer
It is performed under certain circumstances, namely, with Elem = X
If now you mix these different goals in your programs, you get odd results that can only be explained by checking your program in detail.
As a newbie, it is best to stick to only the clean parts of Prolog. In your case:
use dif/2 instead of \==
do not use abbreviations - in your case this limits the number of answers to two. Like in unique_element(X, [a,b,c])
do not use not/1 and (\+)/1 . This leads to even greater inaccuracy. Consider unique_element(a,[a,X]),X=b. that failed abnormally until X=b,unique_element(a,[a,X]) correctly.
Here is a direct cleaned version of your program. There is still room for improvement!
non_member(_X, []). non_member(X, [E|Es]) :- dif(X, E), non_member(X, Es). unique_element(Elem, [Elem|T]) :- non_member(Elem, T). unique_element(Elem, [H|T]) :- dif(H,Elem), % member(Elem, T), % makes unique_element(a,[b,a,a|Xs]) loop unique_element(Elem, T). ?- unique_element(a,[a,X]). dif(X, a) ; false. % superfluous ?- unique_element(X,[E1,E2,E3]). X = E1, dif(E1, E3), dif(E1, E2) ; X = E2, dif(E2, E3), dif(E1, E2) ; X = E3, dif(E2, E3), dif(E1, E3) ; false.
Notice how the last request is read?
When is X unique element of (any) list [E1,E2,E3] ?
The answer is thrice. Examination of one element after another:
X E1 , but only if it is different from E2 and E3
and etc.