40

There are some special operators in Prolog, one of them is is, however, recently I came across the =:= operator and have no idea how it works.

Can someone explain what this operator does, and also where can I find a predefined list of such special operators and what they do?

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
nubela
  • 1
  • 24
  • 75
  • 123

7 Answers7

104

I think the above answer deserves a few words of explanation here nevertheless.

A short note in advance: Arithmetic expressions in Prolog are just terms ("Everything is a term in Prolog"), which are not evaluated automatically. (If you have a Lisp background, think of quoted lists). So 3 + 4 is just the same as +(3,4), which does nothing on its own. It is the responsibility of individual predicates to evaluate those terms.

Several built-in predicates do implicit evaluation, among them the arithmetic comparsion operators like =:= and is. While =:= evaluates both arguments and compares the result, is accepts and evaluates only its right argument as an arithmetic expression.

The left argument has to be an atom, either a numeric constant (which is then compared to the result of the evaluation of the right operand), or a variable. If it is a bound variable, its value has to be numeric and is compared to the right operand as in the former case. If it is an unbound variable, the result of the evaluation of the right operand is bound to that variable. is is often used in this latter case, to bind variables.

To pick up on an example from the above linked Prolog Dictionary: To test if a number N is even, you could use both operators:

0 is N mod 2  % true if N is even
0 =:= N mod 2 % dito

But if you want to capture the result of the operation you can only use the first variant. If X is unbound, then:

X is N mod 2   % X will be 0 if N is even
X =:= N mod 2  % !will bomb with argument/instantiation error!

Rule of thumb: If you just need arithmetic comparison, use =:=. If you want to capture the result of an evaluation, use is.

ThomasH
  • 22,276
  • 13
  • 61
  • 62
  • 13
    Why this wasn't selected as the right answer, I would never know ( ._.) – Igbanam May 28 '13 at 15:44
  • 1
    When using "is" could you have more than one variable on the left-hand side? X + Y = 2 +3 for example. – hiswendy Jun 11 '18 at 21:42
  • @hiswendy What should be the result of this?! Remember that `is` evaluates its right-hand side as an arithmetic expression. That would be 5 in your example. How should 5 than unify with the left-hand side term like `X + Y`?! - The `=/2` predicate you are using is a most general unification function that tries to match and bind two arbitrary terms. It doesn't do automatic arithmetic evaluation, and hence is also quite different from `=:=` which is also discussed here. – ThomasH Jun 13 '18 at 08:37
  • @ThomasH hiswendy is technically correct though in that `?- X + Y = 2 + 3.` produces a result, and that result is `X = 2, Y = 3.` But with CLP arithmetic though, one could do `X + 4 #= 2 + 3.` and get `X = 1.` which is more useful. – Erik Kaplun Jan 25 '21 at 09:55
  • 1
    @ErikKaplun I agree when using `=`. But hiswendy's question concerned `is`, and that doesn't work. – ThomasH Jan 25 '21 at 17:40
28
?- 2+3 =:= 6-1.
true.

?- 2+3 is 6-1.
false.

Also please see docs http://www.swi-prolog.org/pldoc/man?predicate=is/2

Volodymyr Gubarkov
  • 2,173
  • 20
  • 20
  • 4
    Basically an arithmetic operator that checks whether the results of some calculation ends in the same outcome? Kind of like Variable is 5+10 but calculated on both sides and then unified, giving true or false as a result. – G_V Jan 19 '18 at 09:14
20

Complementing the existing answers, I would like to state a few additional points:

An operator is an operator

First of all, the operator =:= is, as the name indicates, an operator. In Prolog, we can use the predicate current_op/3 to learn more about operators. For example:

?- current_op(Prec, Type, =:=).
Prec = 700,
Type = xfx.

This means that the operator =:= has precedence 700 and is of type xfx. This means that it is a binary infix operator.

This means that you can, if you want, write a term like =:=(X, Y) equivalently as X =:= Y. In both cases, the functor of the term is =:=, and the arity of the term is 2. You can use write_canonical/1 to verify this:

?- write_canonical(a =:= b).
=:=(a,b)

A predicate is not an operator

So far, so good! This has all been a purely syntactical feature. However, what you are actually asking about is the predicate (=:=)/2, whose name is =:= and which takes 2 arguments.

As others have already explained, the predicate (=:=)/2 denotes arithmetic equality of two arithmetic expressions. It is true iff its arguments evaluate to the same number.

For example, let us try the most general query, by which we ask for any solution whatsoever, using variables as arguments:

?- X =:= Y.
ERROR: Arguments are not sufficiently instantiated

Hence, this predicate is not a true relation, since we cannot use it for generating results! This is a quite severe drawback of this predicate, clashing with what you commonly call "declarative programming".

The predicate only works in the very specific situation that both arguments are fully instantiated. For example:

?- 1 + 2 =:= 3.
true.

We call such predicates moded because they can only be used in particular modes of usage. For the vast majority of beginners, moded predicates are a nightmare to use, because they require you to think about your programs procedurally, which is quite hard at first and remains hard also later. Also, moded predicates severely limit the generality of your programs, because you cannot use them on all directions in which you could use pure predicates.

Constraints are a more general alternative

Prolog also provides much more general arithmetic predicates in the form of arithmetic constraints.

For example, in the case of integers, try your Prolog system's CLP(FD) constraints. One of the most important CLP(FD) constraints denotes arithmetic equality and is called (#=)/2. In complete analogy to (=:=)/2, the operator (#=)/2 is also defined as an infix operator, and so you can write for example:

| ?- 1 + 2 #= 3.

yes

I am using GNU Prolog as one particular example, and many other Prolog systems also provide CLP(FD) implementations.

A major attraction of constraints is found in their generality. For example, in contrast to (=:=)/2, we get with the predicate (#=)/2:

| ?- X + 2 #= 3.

X = 1

| ?- 1 + Y #= 3.

Y = 2

And we can even ask the most general query:

| ?- X #= Y.

X = _#0(0..268435455)
Y = _#0(0..268435455)

Note how naturally these predicates blend into Prolog and act as relations between integer expressions that can be queried in all directions.

Depending on the domain of interest, my recommendition is to use CLP(FD), CLP(Q), CLP(B) etc. instead of using more low-level arithmetic predicates.

Also see , and for more information.

Coincidentally, the operator =:= is used by CLP(B) with a completely different meaning:

?- sat(A =:= B+1).
A = 1,
sat(B=:=B).

This shows that you must distinguish between operators and predicates. In the above case, the predicate sat/1 has interpreted the given expression as a propositional formula, and in this context, =:= denotes equality of Boolean expressions.

mat
  • 40,498
  • 3
  • 51
  • 78
  • 1
    a very nice answer , mat . I particularly like the way you introduce the usage of op and write_canonical . op is an extremely feature of prolog , in my opinion . – Kintalken May 07 '17 at 06:39
  • However , I disagree strongly with your assertion that an op is not a predicate . Part of the brilliant genius of prolog , in my opinion , is that every op IS a funktor (predicate) . In fact , every element of your source becomes a predicate . In this way it can be seen that the function of tokenizing and parsing in the prolog interprter is to produce a syntax tree , and that syntax tree is entirely specified via funktor . – Kintalken May 07 '17 at 06:41
5

I found my own answer, http://www.cse.unsw.edu.au/~billw/prologdict.html

nubela
  • 1
  • 24
  • 75
  • 123
4

Its an ISO core standard predicate operator, which cannot be bootstrapped from unification (=)/2 or syntactic equality (==)/2. It is defined in section 8.7 Arithmetic Comparison. And it basically behaves as follows:

E =:= F :- 
    X is E, 
    Y is F, 
    arithmetic_compare(=, X, Y).

So both the left hand side (LHS) and right hand side (RHS) must be arithmetic expressions that are evaluted before they are compared. Arithmetic comparison can compare across numeric types. So we have:

   GNU Prolog 1.4.5 (64 bits)

   ?- 0 = 0.0.
   no

   ?- 0 == 0.0
   no

   ?- 0 =:= 0.0.
   yes
1

From Erlang I think it could be good to annotate that as syntax are mostly look alike to Prolog.

=:= expression is meaning of exactly equal.

such as in JavaScript you can use === to also see if the type of the variables are same. Basically it's same logic but =:= is used in functional languages as Prolog, Erlang.

Not much information but hope it could help in some way.

logi-kal
  • 7,107
  • 6
  • 31
  • 43
profiile_samir
  • 191
  • 2
  • 9
0

=:= is a comparison operator.A1 =:= A2 succeeds if values of expressions A1 and A2 are equal. A1 == A2 succeeds if terms A1 and A2 are identical;

Ayyappa Boligala
  • 1,096
  • 7
  • 7