To become a skilled Prolog programmer requires, above all else, practice. However, there are a few standard ways of constructing a program which give some overall structure to the task. Some of these are described below:
tn:br Recursion, decomposing a structure. The key idea is to separate base cases from recursive cases, then make sure that the recursive subgoals all tend towards one or more of the base cases. The general form of this technique is:
member(X, [X|_]). member(X, [_|T]):- member(X, T).
tn:rs Recursion, building up a structure in recursive subgoals. Typically two arguments are used: the first storing the accumulated result and the second being used to "pass back" the final state of the accumulator.
reverse(, Final, Final). reverse([H|T], Sofar, Final):- reverse(T, [H|Sofar], Final).
tn:rb Recursion, building up a structure in the head of each clause. This normally involves just one extra argument which contains one or more variables to be instantiated from successful recursive subgoals.
numbers_in_term(A, [A]):- number(A). numbers_in_term(A + B, Final):- numbers_in_term(A, PA), numbers_in_term(A, PB), append(PA, PB, Final).
tn:cc Committment by cases. If the problem is one which involves a number of mutually exclusive cases then these can be tackled using a sequence of clauses with cuts placed at the points of committment.
has_type(X, variable):- var(X), !. has_type(X, atom):- atom(X), !. has_type(X, number):- number(X), !. has_type(X, structure):- nonvar(X), functor(X, _, N), N > 0.
tn:fdl Failure driven loops to force all solutions. This is often used in combination with printing routines.
all_solutions(Goal):- Goal, write(Goal), nl, fail. all_solutions(_).
tn:rl Repeat loops to perform some task until a terminating condition is obtained. These are often used as replacements for recursive predicates in cases where a simple cycle of repeating and testing is required.
read_until(Prompt, Test):- repeat, write(Prompt), read(Answer), ((Test, !) ; fail).
tn:cf Cut and fail to ensure no solutions on particular cases.
OTHER DEFINITIONS OF P.
no_numbers([H|_]):- number(H), !, fail. no_numbers([_|T]):- no_numbers(T). no_numbers().
tn:dn Double negation to apply a test without binding any variables in the terms used during the test.
unifiable(Term1, Term2):- \+ \+ Term1 = Term2.