Prolog(Sicstus) - setof和findall组合问题

时间:2017-01-06 15:41:50

标签: prolog prolog-setof

给定一个给定电台的路线,例如我们:

route(TubeLine, ListOfStations).

route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...

我需要查找具有特定站点的行的名称。结果必须是非重复的站点,如果没有结果,必须返回一个空列表。所以,查询

| ?- lines(i, Ls).

应该给:

Ls = [blue,red,silver] ? ;
no

我尝试了以下操作:

lines(X, L) :- setof(L1, findall(W, (route(W, Stations),member(X, Stations)),L1), L).

但是,它给出了以下答案:

Is = [[blue,silver,red]];
no

双括号无序。我尝试使用findall,但结果没有订购。我知道我可以编写sort函数并通过它,但是我想知道在这个实例中是否可以使用findall和setof?

1 个答案:

答案 0 :(得分:2)

实际上,它比你的尝试更容易,但你需要掌握自由变量的特殊行为,并考虑到需要未知站的可能性(如果没有解决方案,则setof / 3会失败)。

 lines(X, Ls) :-
   setof(L, Stations^(route(L, Stations), member(X, Stations)), Ls)
   -> true ; Ls = [].

如你所说,更容易的替代方法是使用findall / 3,就像你正在做的那样(没有setof!),并对输出进行排序。