Prolog - 如何执行返回空列表而不是失败的 setof [英] Prolog - how to do setof that returns empty list instead of failing
问题描述
我需要一个满足目标的有序对象列表.setof
负责排序,但在没有对象满足 Goal 时失败.我想像 findall
那样返回一个空列表.
I need an ordered list of Objects that satisfy Goal. setof
takes care of the ordering, but fails when no Objects satisfy Goal. I want to return an empty list instead like findall
does.
这行得通,但是有没有办法不切分地完成这个任务?我正在使用 SWI-Prolog.
This works, but is there a way of accomplishing this without a cut? I'm using SWI-Prolog.
setof(Object, Goal, List), !; List = [].
推荐答案
首先
..., ( setof(Object, Goal, List), ! ; List = [] ), ...
不起作用,正如您所建议的.List = []
总是成功,并且只显示setof/3
的第一个答案.但是 setof/3
可能会产生几个答案.适用于任何 Prolog 的一般方法是:
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) ), ...
许多实现为此提供了一个实现特定的控制结构,以避免 Goal
被调用两次.例如.if/3
(SICStus、YAP)或 (*->)/2
(SWI、GNU):
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 = [] ), ...
新变量 ListX
对于 List
已经实例化的情况(不可否认)是必需的.
The new variable ListX
is necessary for the (admittedly rare) case that List
is already instantiated.
请注意,其他两个答案都不能完全满足您的要求.
这篇关于Prolog - 如何执行返回空列表而不是失败的 setof的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!