First,
..., ( setof(Object, Goal, List), ! ; List = [] ), ...
does not work, as you suggest. It always succeeds for List = []
, and it only shows the first answer of setof/3
. But setof/3
may produce several answers. The general method that works in any Prolog is:
..., ( \+ Goal -> List = [] ; setof(Object, Goal, List) ), ...
Many implementations offer an implementation specific control construct for this which avoids that Goal
is called twice. E.g. if/3
(SICStus, YAP), or (*->)/2
(SWI, GNU):
..., if( setof(Object, Goal, ListX), ListX = List, List = [] ), ...
..., ( setof(Object, Goal, ListX) *-> ListX = List ; List = [] ), ...
The new variable ListX
is necessary for the (admittedly rare) case that List
is already instantiated.
Note that both other answers do not produce exactly what you asked for.