When there are many solutions to a goal, and a list of all those solutions is desired, one means of collecting them is to write a procedure that repeatedly backtracks into that goal to get another solution. In order to collect all the solutions together, it is necessary to use the database (via assertion) to hold the solutions as they are generated, because backtracking to redo the goal would undo any list construction that had been done after satisfying the goal.
The writing of such a backtracking loop can be avoided by the use of
one of the built-in predicates
findall/[3,4], which are described below. These provide a nice
logical abstraction, whereas with a user-written backtracking loop the
need for explicit side-effects (assertions) destroys the declarative
interpretation of the code. The built-in predicates are also more
efficient than those a user could write.
If the solutions being collected contain attributed variables
(see lib-atts) or suspended goals (see ref-sem-sec), then
those attributes are not retained in the list of solutions. To retain the
attributes, you can use
copy_term/3 (see ref-lte-cpt).