Cuts are often used to give a range of behaviours of the program under
special circumstances, with a ``catch--all'' default definition at the end.
Consider, for example, the following program, which is discussed in
Sterling & Shapiro ``The Arto of Prolog''. We want to define a predicate
which will be able to
determine a pension for some person (X
), given certain
characteristics of X
. The default is nothing
but,
before that we put a series of tests to see if X
qualifies for
any pension. The code we use is:
pension(X, invalid_pension):- invalid(X), !. pension(X, old_age_pension):- over_65(X), paid_up(X), !. pension(X, supplementary_benefit):- over_65(X), !. pension(_, nothing). % This is the default if none of the above succeed.
Let's also define some characteristics for a sample of people.
invalid(fred). over_65(fred). over_65(joe). over_65(jim). paid_up(fred). paid_up(joe).
This works fine for queries such as pension(fred,P)
, which
would instantiate P
to invalid
and return no further
results. However, there are ways of forcing the program to give
incorrect recommendations. In particular, the query
pension(fred,nothing)
would succeed. How can this be fixed?
One way is to make it explicit that the default of nothing
only
applies when there is no possible pension. In the code below, this is
achieved by inventing a new predicate, entitlement/2
which
makes this distinction.
entitlement(X, Y):- possible_pension(X, Y). entitlement(X, nothing):- \+ possible_pension(X, _). possible_pension(X, invalid_pension):- invalid(X). possible_pension(X, old_age_pension):- over_65(X), paid_up(X). possible_pension(X, supplementary_benefit):- over_65(X).