A shelf is an anonymous object which can be used to store information across failures. A typical application is counting of solutions, keeping track of the best solution, aggregating information across multiple solutions, etc.
A shelf is an object with multiple slots whose contents survive backtracking. The content of each slot can be set and retrieved individually, or the whole shelf can be retrieved as a term.
Shelves come in two flavours: anonymous shelves are created with shelf_create/2 or shelf_create/3 and referred to by handle, while named shelves are created with a shelf/ 2 declaration and referred to by their name within a module. If possible, anonymous shelves should be preferred because they make it easier to write robust, reentrant code. For example, an anonymous shelf automatically disappears when the system backtracks over its creation, or when the store handle gets garbage collected. Named shelves, on the other hand, must be explicitly destroyed in order to free the associated memory.
All shelf slots are initialized when the shelf is created. Data is stored in the slots (or the shelf as a whole) with shelf_set/3 and retrieved with shelf_get/3.
Example: Counting how many solutions a goal has:
count_solutions(Goal, Total) :- shelf_create(count(0), Shelf), ( call(Goal), shelf_get(Shelf, 1, Old), New is Old + 1, shelf_set(Shelf, 1, New), fail ; shelf_get(Shelf, 1, Total) ).
In this particular example, we could have used shelf_inc/2 to increment the counter.