I have startet to learn Prolog and I want to get a list of opponents of players with findall/3. In the Generalization I just want to add only the opponents to the list who are actually players, except the player I am asking for itself. How can I formulate this exception? I know about the negation as failure concept but I am not sure if and how I need it here.
player(irina).
player(anton).
player(michael).
opponent(irina, anton).
opponent(irina, maria).
opponent(irina, michael).
% Only opponents who are also players should be added to the list,
% except the player of interest itself
opponent(X, Y) :- X \= Y, player(Y).
% the query
?- findall(O, opponent(irina,O) , OpponentList).
% the result
% only the first three results from the facts,
% the results from the rule, a second entry of
% anton and michael are missing.
OpponentList = [anton, maria, michael].
I actually expected, that the resolution would work as follows:
opponent(irina, irina) :- irina \= irina, player(irina).
% false true
% false
% false, hence not added to the list
opponent(irina, anton) :- irina \= anton, player(anton).
% true true
% true
% true, hence added to the list
What am I missing? Many thanks in advance!
Code:
Run it:
Not expected:
Expected:
So what happens in the "not expected" case with
Who=irina:findall/3tries to collect all values Y such thatopponent(Who,O)anton,maria,michalthrough the factsopponent(irina, anton).opponent(irina, maria).opponent(irina, michael).opponent(X, Y) :- ...withX=irina(once only). But the testX \= Yfails becauseXhas been constrained to beirinabutYis still fresh (completely unconstrained). This means that a unification ofXandYcould succeed if it were attempted (which is what is being tested,=does not as such mean "is not equal"). SoX \= Yis false at this point of computation. If you moveX \= Yafterplayer(Y), thenYwill have been constrained to whatever was grabbed from theplayer/1facts, and this would reduce to an actual comparison of the values ofXandY.