Prolog - 如何做setof返回空列表而不是失败

时间:2013-12-05 18:05:47

标签: prolog prolog-setof

我需要一个满足目标的有序对象列表。 setof负责排序,但在没有对象满足目标时失败。我想返回一个空列表,而不是像findall那样。

这样可行,但有没有一种方法可以在没有削减的情况下实现这一目标?我正在使用SWI-Prolog。

setof(Object, Goal, List), !; List = [].

3 个答案:

答案 0 :(得分:5)

首先,

..., ( 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已经实例化的(诚然罕见)情况是必要的。

请注意,其他答案并不能完全符合您的要求。

答案 1 :(得分:1)

(setof(Object, Goal, List) ; List = [])

也会起作用(setof本身就是确定性的)。

为了确保摆脱选择点,我们需要更加冗长的

(setof(Object, Goal, List) -> true ; List = [])

编辑目前,我的答案显然是错误的,或者至少非常不完整。经过虚假评论和回答后,我会建议

setof(Object, Goal, List) *-> true ; List = [].

答案 2 :(得分:0)

如果您不需要setof 的潜在非确定性或可变量化功能,您可以坚持使用findall / 3。这是确定性的,不会失败:

?- findall(X, fail, Xs).
Xs = []
yes

然后,您可以使用sort / 2对结果进行排序:

findall(Object, Goal, UnsortedWithDuplicates),
sort(UnsortedWithDuplicates, List)