Equality in Prolog and you

Posted on October 11, 2012

Once upon a time, a friend of mine searched for the equality operator in prolog: he entered = in SWI-Prolog’s predicate search. The results?


To be fair, (=<)/2 is for comparison, (=\=)/2 is not equal and (=../2) is a special operator that is only loosely related to equality. Still, that leaves 4 operators - 5 if we consider the infamous is/2.


The “assignment” operator (although, as Prolog does not really have assignments, a better name might be unificator): it will try to unify the two terms, instantiating any variables. If it’s not possible to unify them, it will fail.


The closest prolog has to an equality check operator; it will not perform any unifications, just compare the two terms. Two variables with different names (e.g. Foo and Bar) are consider different!

Much confusion is caused by the fact that the two operators are equivalent if the two terms are ground (i.e. they contain no free variables). In that case, no further unification can be done so = will succeed if they are equal and fail if they are not, just like ==


Ah, the infamous is. It will evaluate the expression on its right side and (attempt to) unify the result with the term on its left side. Naturally, this will fail: X+Y is 1+2 as the evaluated expression is a number, 3 and it cannot be matched with X+Y - contrast with X+Y = 1+2, which will result in X = 1 and Y = 2. Also, is can be used to check if the evaluated expression is equal to a value (e.g. 0 is 1-1).


Moving to more exotic operators. This operator accepts two expressions, evaluates them, and returns true if they are equal; otherwise false. Note that an integer will be considered equal to a real (e.g. 1 =:= 1.0 returns true). Contrast with 1 == 1.0 which returns false; therefore you cannot always replace X =:= Y with Xi is X, Yi is Y, Xi == Yi


To quote the manual:

+Term1 =@= +Term2
True if Term1 is a variant of (or structurally equivalent to) Term2. Testing for a variant is weaker than equivalence (==/2), but stronger than unification (=/2). Two terms A and B are variants iff there exists a renaming of the variables in A that makes A equivalent (==) to B and vice versa.

Will you ever need it? Probably not.


Closing with this operator just because it was mentioned. It is not really an operator related to equality; it is called the univ operator and is used to construct/deconstruct terms:

?- foo(4,2) =.. L.
L = [foo, 4, 2].
?- X =.. [foo, 4, 2].
X = foo(4, 2).

And you can call X by doing call(X). It’s quite exciting and useful for constructing terms at runtime, with the usual pitfalls of eval-like functions.
However, I wouldn’t recommend using it, especially if you are new to prolog; if you need to use it, you most likely have a wrong representation of your data - maybe you should construct a list with them or do some pattern matching first.

Don’t panic

Having 3 commonly used operators for equality (and another 3 less used) might be daunting - but it’s a result of the greater flexibility that comes with having uninstantiated variables and no implicit evaluation of arithmetic expressions. Of course, as always, whether it’s actually worth it depends on the given task and the way it’s approached.