Prolog (Sicstus) - setof 和 findall 组合问题
Prolog (Sicstus) - setof and findall combination issues
给定站点的一组路线,例如我们:
route(TubeLine, ListOfStations).
route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...
我需要查找具有特定站点的公共线路名称。结果必须排序,具有非重复站并且必须 return 一个空列表,如果没有结果。所以,查询
| ?- 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,但结果没有排序。我知道我可以编写排序函数并将其传递,但是我想知道在这种情况下是否可以只使用 findall 和 setof?
实际上,这比您的尝试更容易,但您需要掌握自由变量的特殊行为,并考虑到需要未知站点的可能性(setof/3 如果没有解决方案则失败).
lines(X, Ls) :-
setof(L, Stations^(route(L, Stations), member(X, Stations)), Ls)
-> true ; Ls = [].
如您所说,更简单的替代方法是完全按照您的操作使用 findall/3(不使用 setof!),然后对输出进行排序。
给定站点的一组路线,例如我们:
route(TubeLine, ListOfStations).
route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...
我需要查找具有特定站点的公共线路名称。结果必须排序,具有非重复站并且必须 return 一个空列表,如果没有结果。所以,查询
| ?- 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,但结果没有排序。我知道我可以编写排序函数并将其传递,但是我想知道在这种情况下是否可以只使用 findall 和 setof?
实际上,这比您的尝试更容易,但您需要掌握自由变量的特殊行为,并考虑到需要未知站点的可能性(setof/3 如果没有解决方案则失败).
lines(X, Ls) :-
setof(L, Stations^(route(L, Stations), member(X, Stations)), Ls)
-> true ; Ls = [].
如您所说,更简单的替代方法是完全按照您的操作使用 findall/3(不使用 setof!),然后对输出进行排序。