所以我试图通过直接在split中使用sort库谓词来摆脱wrapper子句。分裂的作用是从列表中生成一个如下所示的数字列表:[1:2,3:2,4:6] --- split - > [1,2,3,2,4,6]。但是生成的列表包含重复项,我不希望这样,所以我使用包装器来组合拆分和排序,然后生成所需的结果:[1,2,3,4,6]。
我真的想摆脱包装器,只是在split中使用sort,但是我一直得到“ERROR:sort / 2:参数没有被充分实例化”。有任何想法吗?谢谢:))
split([],[]).
split([H1:H2|T],[H1,H2|NT]) :-
split(T,NT).
wrapper(L,Processed) :-
split(L,L2),
sort(L2,Processed).
答案 0 :(得分:1)
我真的想摆脱包装器,只需在split
中使用sort
然后使用具有复杂目标的findall
,例如
split(Edges, NodeSet) :-
findall(Node,
(member(Edge, Edges), (Edge = (Node:_); Edge = (_:Node))),
NodeList),
sort(NodeList, NodeSet).
但是,一旦开始使用聚合谓词,您也可以跳过sort
并使用setof
:
split(Edges, NodeSet) :-
setof(Node, Edge^Pair^(member(Edge, Edges),
Edge =.. [:|Pair],
member(Node,Pair)),
NodeSet).
读作:获取所有Node
s.t的集合。存在Edge
并且存在Pair
s.t. (等)并称之为NodeSet
。
=..
(“univ”)运算符解构了一对:Edge =.. [:, Left, Right]
。为了更好的可读性,您可以编写单独的谓词来从边缘获取节点:
% endpoint(Edge, Node) is true iff Node is an endpoint of Edge
endpoint(Node:_, Node).
endpoint(_:Node, Node).
split(Edges, NodeSet) :-
setof(Node, Edge^(member(Edge, Edges), endpoint(Edge, Node)), NodeSet).
编辑在尝试此方法之前,请参阅下面的讨论,了解这是否比OP的原始代码更好。