One very important, and very tricky, predicate is the 'cut', written
!. This is quite dangerous in inexperienced hands (such as yours!). It
is an instruction to Prolog not to back-track looking for other solutions. Here
is an example:
In dealing with data-base Prolog, we discovered that the
correct definition of brother/2 and sister/2 require a test
for inequality:
sister(X,Y):- female(X), parent(P, X), parent(P, Y), different(X,Y).
We
know how to check that two terms are the same (by unification, using
=/2), but how do we check that they are different? In principle by
checking that they do NOT unify. In fact, Prolog has a built-in predicate
\+/1 which allows this to be done:[6]
e.g.
| ?- \+ a=b. yes
So
different/2 could be programmed as:
different(X, Y):- \+ X=Y.
The
interesting thing from the present perspective is how \+/1 itself is
programmed. The standard definition is this:
\+ X:- X, !, fail. \+ X.
These
clauses MUST occur in this order, if the definition is to work. When
\+ term is called, X is instantiated to term,
and the first call in the body of the first clause of \+/1 tests to
see if term is true. If it is known to the Prolog data-base, this call
will succeed and control will pass to !/0 ('cut'). Cut always
succeeds, so control passes to the built-in predicate fail/0.
fail/0 always fails. (Surprise, surprise.)
Normally, when a
goal fails, Prolog backtracks to see if there are any alternative solutions.
Here, to see if term has any more solutions. It will then repeat the
procedure until all the possibilities have been exhausted, at which point
control would pass to the second clause of \+/1, which (since it has
no conditions) would succeed.
However, the presence of the cut in the
first clause prevents this behaviour. Instead, when the call to cut has
succeeded, Prolog cuts away all the information about alternative choices
before the cut. Therefore, when fail/0 is encountered, there is
nowhere else to go and the call \+ term fails straightaway.
The only
situation in which the second clause will be reached is if term itself
fails. This will be the case if term can't be found in the Prolog
database, or proved.
So, \+ a=b will fail if a=b; and
will succeed if a=b fails.
Read carefully a Prolog textbook
before using the cut yourself. (Using \+/1 is OK, provided you realise
that when it fails its 'meaning' is 'Prolog was unable to find a solution'.
I.e. 'don't know', rather than false. This definition of negation is called
'negation by failure'.
[6] \+/1 is defined as a prefix operator, so the normal brackets are not needed (unless what you are negating is a compound expression containing conjunctions or disjunctions.