Concepts of Programming Languages

(Sean Pound) #1
16.7 Deficiencies of Prolog 753

member(Element, [Element | _]) :- !.


Backtracking will not attempt to resatisfy member but instead will cause the
entire subgoal to fail.
Cut is particularly useful in a programming strategy in Prolog called gen-
erate and test. In programs that use the generate-and-test strategy, the goal
consists of subgoals that generate potential solutions, which are then checked
by later “test” subgoals. Rejected solutions require backtracking to “generator”
subgoals, which generate new potential solutions. As an example of a generate-
and-test program, consider the following, which appears in Clocksin and Mel-
lish (2003):


divide(N1, N2, Result) :- is_integer(Result),
Product1 is Result N2,
Product2 is (Result + 1)
N2,
Pr oduct1 =< N1, Product2 >
N1, !.


This program performs integer division, using addition and multiplication.
Because most Prolog systems provide division as an operator, this program is
not actually useful, other than to illustrate a simple generate-and-test program.
The predicate is_integer succeeds as long as its parameter can be
instantiated to some nonnegative integer. If its argument is not instantiated,
is_integer instantiates it to the value 0. If the argument is instantiated to an
integer, is_integer instantiates it to the next larger integer value.
So, in divide, is_integer is the generator subgoal. It generates ele-
ments of the sequence 0, 1, 2, ... , one each time it is satisfied. All of the other
subgoals are the testing subgoals—they check to determine whether the value
produced by is_integer is, in fact, the quotient of the first two parameters,
N1 and N2. The purpose of the cut as the last subgoal is simple: It prevents
divide from ever trying to find an alternative solution once it has found the
solution. Although is_integer can generate a huge number of candidates,
only one is the solution, so the cut here prevents useless attempts to produce
secondary solutions.
Use of the cut operator has been compared to the use of the goto in imper-
ative languages (van Emden, 1980). Although it is sometimes needed, it is pos-
sible to abuse it. Indeed, it is sometimes used to make logic programs have a
control flow that is inspired by imperative programming styles.
The ability to tamper with control flow in a Prolog program is a deficiency,
because it is directly detrimental to one of the important advantages of logic
programming—that programs do not specify how solutions are to be found.
Rather, they simply specify what the solution should look like. This design
makes programs easier to write and easier to read. They are not cluttered with
the details of how the solutions are to be determined and, in particular, the
precise order in which the computations are done to produce the solution. So,
while logic programming requires no control flow directions, Prolog programs
frequently use them, mostly for the sake of efficiency.

Free download pdf