next up previous contents
Next: Some Practical Problems Up: Some General Program Previous: Test --- Process

Failure-Driven Loop

We now introduce an extremely procedural programming technique for simulating a kind of iteration. The idea is deliberately generate a term and then fail. This suggests the useless schema

 
 failure_driven_loop( Info):-

generate( Info,Term),

fail.

failure_driven_loop( Info).

Provided that the generator eventually fails any version of this schema will always succeed --- i.e. it will be equivalent to true.

We now use side effecting predicates to do something useful with the generated term.

A side-effecting predicate is one that is (often) logically equivalent to true but also does something else that is non-logical. For example, write/1 and nl/0 have the side-effect of writing material onto the terminal screen (usually). Also, consult/1 and reconsult/1 have the side-effect of changing the program. The predicate read/1 has the side-effect of destructively reading input from the terminal (or whatever).

To illustrate the problem: if we query Prolog with the goal (write(hello),fail) then write/1 will be used to write hello on (we assume) the terminal screen and the call to fail/0 will fail. Now, logically, we have a statement with the truth value of false ---so we have proved that the goal cannot succeed and therefore there should be no message ( hello) on the screen.

Here is another example: if we try the goal (read(X),fail) then read/1 will be used to read some input from the user (we assume) and the call to fail/0 will fail. Again, we have a statement with the truth value of false ---so the input should still be available for consideration. Yet we taken input from the keyboard (or somewhere) and we do not put that input back so that it can be reconsidered. The input has been consumed.

We can see that any predicate succeeds generating an effect that cannot be undone on backtracking must be a side-effecting predicate.

The complete failure-driven loop schema can be taken as:

 
 failure_driven_loop( Info):-

generate( Info,Term),

side_effect(Term),

fail.

failure_driven_loop( Info).

This can be elaborated by having several side-effecting predicates, replacing the fail/0 with some other predicate that fails and so on.

We illustrate with a simple example. We will use int/1 as a finite generator and then print out the valid arguments for this relation on the screen.

 
int(1).

int(2).

int(3).

int(4).

int(5).

print_int:-

int(X),

write(X),nl,

fail.

print_int.

This programming technique can be very useful. In the early days, it was overused because it was space-efficient.



next up previous contents
Next: Some Practical Problems Up: Some General Program Previous: Test --- Process



Paul Brna
Mon May 24 20:14:48 BST 1999