Finding All the Solutions at Once

In chapter 6, we compared backtracking and recursion as ways to perform repetitive processes. Recursion won out because, unlike backtracking, it can pass information (through arguments) from one recursive call to the next. Because of this, a recursive procedure can keep track of partial results or counters as it goes along.

But there's one thing backtracking can do that recursion can't do--namely, find all the alternative solutions to a goal. So you may find yourself in a quandary: You need all the solutions to a goal, but you need them all at once, as part of a single compound data structure. What do you do?

Fortunately, Visual Prolog provides a way out of this impasse. The built-in predicate findall takes a goal as one of its arguments and collects all of the solutions to that goal into a single list. findall takes three arguments:

The first argument, VarName, specifies which argument in the specified predicate is to be collected into a list.

The second, mypredicate, indicates the predicate from which the values will be collected.

The third argument, ListParam, is a variable that holds the list of values collected through backtracking. Note that there must be a user-defined domain to which the values of ListParam belong.

Program 8 uses findall to print the average age of a group of people.

/* Program ch07e08.pro */

The findall clause in this program creates a list, L, that is a collection of all the ages obtained from the predicate person. If you wanted to collect a list of all the people who are 42 years old, you could give the following subgoal:

    findall(Who, person(Who, _, 42), List)

Before trying this, please note that it requires the program to contain a domain declaration for the resulting list:

    slist = string*