You have already seen several programs which contain an anonymous
variable, i.e. a variable which either is given as an underscore
_, or whose name begins with an underscore
(e.g. _Tail).
If you consult and then list a program which contains such a variable,
SICStus shows an underscore only in both cases.
Anonymous variables is something which you have a reason to use quite often, as it is a Prolog convention to use a name beginning with an underscore for variables whose value is not used in the clause in question.
Prolog is a declarative language, whose control structure relies on the unification of heads and goals. That is, facts and rules are accessed by matching predicates and variables. When the goal of a query matches a head of a rule, the variables in the head are instantiated (or if the query is called with a variable, the variables of the head are unified with the variables in the query). The goals of the rule are called with these variable bindings. The most important function of variables is thus that they pass on values or bindings.
When we write a procedure, i.e. all the facts and rules which define
a particular predicate, it is not always the case that each argument,
or part of an argument, is used by every individual clause.
This was seen by the list/1 procedure on handout 7:
list([]).
list([_Head|Tail]):-
list(Tail).
In the second clause, we only need to verify that there is a
head. We do not need to know what the head actually looks like, and
the variable is not used in the goal of the rule.
This is the sort of situation where an anonymous variable should be
used.
In fact, if you do not use a name which begins by an underscore,
SICStus will complain when you consult the file (it says
something like
{Warning: [Tail] - singleton variables in member/2 in lines
14-18}
You can have several underscores in the same clause, and they will
each be treated separately: for instance, f(_,_) would unify
with f(x,y).
It is good programming style to use an underscore followed by a name rather than just an underscore when you write the program. The reason for this is that by chosing your variable names carefully, you make your programs easier to read.
Remember the ancestor predicate from the chapter on Recursion.
ancestor(Old,Young) :-
parent(Old,Young).
ancestor(Old,Young) :-
parent(Old,Middle),
ancestor(Middle,Young).
We could just as well have replaced Old by X,
Middle by Y and Young by Z but it would
have been more difficult to read.
It pays off to choose your variable names carefully.
<a.von.klopp@bangor.ac.uk>