Now we look at another fundamental schema. The idea with test --- process is to guarantee that some inputs will only be `processed' if the input passes a test.
test_process( Info X Y):-where we assume that the Info is 0 or more arguments which are all input arguments the last but one argument is an input argument and the last argument is a output argument. Although this gives a very procedural view it is often possible to give a declarative reading.test( Info X)
process( Info X Y).
We usually want to make sure thatIn short we often want only one way of finding an output.
- test does not have alternative ways of confirming that the generated element is ok
- process does not have alternative ways of `processing' the input
We have already met a program that satisfies this schema ---one for parity/2 (which is slightly rewritten here).
parity(X Y):-This example illustrates that if the input argument is an integer then we see two cases: either the integer is even or it is odd. There is no third case. Nor can any integer be both even and odd.odd(X)
Y=odd.
parity(X Y).
\+(odd(X))Y=even.
plus set of facts defining odd/1
As in the above example the usage of test --- process is closely coupled with the idea of writing all the clauses for a predicate in this form ---each clause is designed to handle one `class' of input. The whole scheme falls down if we do not design the `classes' of input to be disjoint -- i.e. no input falls into more than one category. We also require that each input falls in at least one category ---to summarise each input falls in one and only one class.
We can show a previous example which does not properly use the test --- process schema (for good reasons). Modifying the code using this schema results in a different and useful program.
member(Element [ElementNow member/2 can be used as a generator if the first argument is a variable and its second argument is a list ---as in the goal member(X [a b c d e f]. The first solution for X is the first element of the list [a b c d e f]. On redoing we get in succession X bound to the different elements in the list.Tail]).
member(Element [Head
Tail]):-
member(Element Tail).
We now rewrite using the test --- process schema. We also rename the predicate to the standard name of memberchk/2 (this is its usual name in libraries of Prolog code).
memberchk(Element [HeadTail]):-
Element = Head.
memberchk(Element [Head
Tail]):-
\+(Element = Head)memberchk(Element Tail).
This will no longer generate alternative solutions on backtracking for the goal memberchk(X [a b c d e f]) (because there are no alternative ways of resatisfying it). If the mode of use is mode memberchk(+ +) then the meaning is that we check that the first argument is an element of the list (which is the second argument).