Cut is also commonly used in conjunction with the
generate-and-test programming paradigm. For example, consider the
find_solution/1 defined by
find_solution(X) :- candidate_solution(X), test_solution(X), !.
candidate_solution/1 generates possible answers on
backtracking. The intent is to stop generating candidates as soon
as one is found that satisfies
test_solution/1. If the cut
were omitted, then a future failure could cause backtracking into this
clause and restart the generation of candidate solutions. A
similar example is shown below:
process_file(F) :- see(F), repeat, read(X), process_and_fail(X), !, seen. process_and_fail(end_of_file) :- !. process_and_fail(X) :- process(X), fail.
The cut in
process_file/1 is another example of terminating
a generate-and-test loop. In general, a cut should always be
placed after a
repeat/0 so that the backtracking loop is
clearly terminated. If the cut were omitted in this case, then on
later backtracking Prolog might try to read another term
after the end of the file had been reached.
The cut in
process_and_fail/1 might be considered
unnecessary because, assuming the call shown is the only call to it, the
process_file/1 ensures that backtracking into
process_and_fail/1 can never happen. While this is true, it is
also a good safeguard to include a cut in
process_and_fail/1 because someone may unwittingly change
process_file/1 in the future.