I'm trying out an exercise where I have to write the predicate, colors/2
(or colors(C1,C2) :-
...) that runs like the following:
?- colors(red,blue).
true.
?- colors(red,red).
false.
?- colors(blue,blue).
false.
So, essentially, I have to write my predicate in a manner where it doesn't accept when you enter the same color twice.
I am defining my facts to be:
col(red,blue).
col(purple,orange).
col(green, yellow).
I am making my predicate to be:
colors(X,Y) :- (col(X,Y); col(Y,X)) not (col(X,X); col(Y,Y)).
I don't understand why my predicate won't work. It is returning a syntax error with "Operator Expected." I am saying that it doesn't matter in what order you write the facts. Meaning, you can say colors(red,blue) or colors(blue,red), but you can't query colors with the same name without it returning false.
I would like to know:
A couple of things:
You're missing a comma (,
) before not
and not/1
expects a single term in parentheses, so use more parentheses:
colors(X,Y) :- (col(X,Y); col(Y,X)), not( (col(X,X); col(Y,Y)) ).
As @PauloMora indicated, not/1
is deprecated in favor of the ISO \+/1
, so better would be:
colors(X,Y) :- (col(X,Y); col(Y,X)), \+ (col(X,X); col(Y,Y)).
Then looking at col(X,X)
and col(Y,Y)
, there are no facts or predicates where col(X,X)
would be true (both arguments are the same). So each of these will always be false, and \+ (col(X,X); col(Y,Y))
will always be true. So the expression is superfluous, and your predicate becomes (at least with the pattern established in your current set of facts):
colors(X,Y) :- col(X,Y) ; col(Y,X).
Since you don't have any facts stipulated with matching colors (col(x,x)
), then queries like col(red, red)
will fail anyway.
X
and Y
, the appropriate mechanism would be dif(X, Y)
:
colors(X, Y) :- (col(X, Y) ; col(Y, X)), dif(X, Y).
The parentheses are desired since ,
has higher precedence than ;
. This would guard against the case where you happened to have a fact or predicate col/2
in which both arguments were the same (identical or unified).