我需要一个满足目标的对象的有序列表。setof
负责排序,但在没有对象满足目标时失败。我想返回一个空列表而不是像findall
那样。
这行得通,但是有没有办法在没有削减的情况下完成这个?我正在使用 SWI-Prolog。
setof(Object, Goal, List), !; List = [].
我需要一个满足目标的对象的有序列表。setof
负责排序,但在没有对象满足目标时失败。我想返回一个空列表而不是像findall
那样。
这行得通,但是有没有办法在没有削减的情况下完成这个?我正在使用 SWI-Prolog。
setof(Object, Goal, List), !; List = [].
第一的,
..., ( setof(Object, Goal, List), ! ; List = [] ), ...
正如你所建议的那样不起作用。它总是成功List = []
,并且只显示 的第一个答案setof/3
。但setof/3
可能会产生几个答案。适用于任何 Prolog 的通用方法是:
..., ( \+ Goal -> List = [] ; setof(Object, Goal, List) ), ...
许多实现为此提供了一个实现特定的控制结构,以避免Goal
被调用两次。例如if/3
(SICStus、YAP)或(*->)/2
(SWI、GNU):
..., if( setof(Object, Goal, ListX), ListX = List, List = [] ), ...
..., ( setof(Object, Goal, ListX) *-> ListX = List ; List = [] ), ...
对于已经实例化ListX
的(诚然罕见的)情况,新变量是必需的。List
请注意,其他两个答案都不能完全满足您的要求。
(setof(Object, Goal, List) ; List = [])
也会起作用(setof 本身是确定性的)。
为了确保摆脱选择点,我们需要更详细一点
(setof(Object, Goal, List) -> true ; List = [])
就目前的情况进行编辑,我的回答显然是错误的,或者至少非常不完整。在虚假评论和回答之后,我会建议
setof(Object, Goal, List) *-> true ; List = [].
如果您不需要潜在的不确定性或 setof 的变量量化功能,您可以坚持使用 findall/3。这是确定性的并且不会失败:
?- findall(X, fail, Xs).
Xs = []
yes
然后,您可以使用 sort/2 自己对结果进行排序:
findall(Object, Goal, UnsortedWithDuplicates),
sort(UnsortedWithDuplicates, List)