PrologEZ
Data & computation · Lesson 16 of 43

Built-in operators and math

Operators as predicates, evaluation with is/2, comparison, and the resolution of sum/2.

Ad-hoc math in Prolog

A Prolog operator is a binary predicate that can be used in infix notation. For example =/2 can be used to unify two terms, and \=/2 to check non-unification.

Values and operators:

  • you can use 10, -20.1, 1.3e-4 as ground terms;
  • the operators =:=, =\=, >=, =< (note: not <=!), >, < are modelled as 2-ary predicates working on numbers as expected. They are not relational: both arguments must be ground;
  • you can build terms using +, -, *, / as 2-ary functors, also possibly in infix notation. Such terms are actually an abstract syntax tree of a math expression;
  • the operator is/2 can be used to evaluate its second argument to a number, unified with the first argument;
  • watch out: do not use is/2 to unify terms, it is not idiomatic.

Very often, predicates doing math are not relational.

Operators at work

File operators.pl:

?- '='(p(1, 2), p(X, Y))
?- p(1, 2) = p(X, Y)
?- p(1, 2) = p(_, 3)
?- '>'(20, 10)
?- 20 > 10
?- 10 > 20
?- 10 =:= 20
?- 10 =\= 20
?- X = 10 + 20
?- is(X, '+'(10, 20))
?- X is 10 + 20
?- 30 is 10 + 20
?- 10 is p(20)
?- 10 is X + 5
  • X = 10 + 20 binds X to the term '+'(10, 20): + is just a functor, nothing is computed;
  • the last two goals raise exceptions (a type error and an instantiation error). They abort the computation with an exception. Here they are shown in red.

Working with math: sum/2

File sum.pl. The sum of a list of numbers:

% relates a list with the sum of its elements
sum([], 0).
sum([H|T], S) :- sum(T, N), S is H + N.
?- sum([10, 20, 30], S)
?- sum([], S)
?- sum([10, 20, 30], 60)

The resolution of sum([10, 20, 30], S):

sum([10,20,30], S)
sum([20,30], S'), S is 10 + S'
sum([30], S''), S' is 20 + S'', S is 10 + S'
sum([], S'''), S'' is 30 + S''', S' is 20 + S'', S is 10 + S'
S'' is 30 + 0, S' is 20 + S'', S is 10 + S'
S' is 20 + 30, S is 10 + S'
S is 10 + 50
{S/60}

Notice that the additions only happen after the recursion has reached the empty list: is/2 needs its right-hand side fully known.

Wrap-up on terminology

File terminology.pl. Take the program for element/2 and the goal below:

element(E, cons(E, _)).
element(E, cons(_, T)) :- element(E, T).
?- element(b, cons(a, cons(b, cons(c, nil))))

Use this to review all the vocabulary:

  • terms: E is a variable; _ is the wildcard variable; a is an atom; cons is a functor name; cons(E, _) is a compound non-ground term; cons(a, nil) is a compound ground term;
  • program: lines 1 and 2 are clauses; line 1 is a fact, line 2 is a rule; the part before :- is the head, the part after is the body; element is a predicate;
  • resolution: the part after ?- is the resolvent, a list of goals; the tree's root is the initial resolvent, an arc is a resolution step; "yes" is a solution, "no" is a failure; traversing from a node to one at a higher level in the tree is backtracking.

Exercise: Product of a list

Write product(List, P): P is the product of the numbers of the list, written like sum/2 above. The product of the empty list is 1. For example product([2, 3, 4], P) gives P = 24.