Reputation: 3673
So I'm trying to get rid of the wrapper clause by using the sort library predicate directly inside split. What split does is just generating a list of numbers from a list that looks like this: [1:2,3:2,4:6] ---split--> [1,2,3,2,4,6]. But the generated list contains duplicates, and I don't want that, so I'm using the wrapper to combine split and sort, which then generates the desired result: [1,2,3,4,6].
I'd really like to get rid of the wrapper and just use sort within split, however I keep getting "ERROR: sort/2: Arguments are not sufficiently instantiated." Any ideas? Thanks :)
split([],[]).
split([H1:H2|T],[H1,H2|NT]) :-
split(T,NT).
wrapper(L,Processed) :-
split(L,L2),
sort(L2,Processed).
Upvotes: 1
Views: 1056
Reputation: 363487
I'd really like to get rid of the wrapper and just use sort within split
Then use findall
with a complex goal such as
split(Edges, NodeSet) :-
findall(Node,
(member(Edge, Edges), (Edge = (Node:_); Edge = (_:Node))),
NodeList),
sort(NodeList, NodeSet).
However, once you start using aggregating predicates, you could just as well skip the sort
and use setof
:
split(Edges, NodeSet) :-
setof(Node, Edge^Pair^(member(Edge, Edges),
Edge =.. [:|Pair],
member(Node,Pair)),
NodeSet).
Read as: get the set of all Node
s.t. there exists Edge
and there exists Pair
s.t. (etc.) and call that NodeSet
.
The =..
("univ") operator deconstructs a pair: Edge =.. [:, Left, Right]
. For better readability, you can write a separate predicate to get nodes from edges:
% 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).
EDIT Before you try this approach, see the discussion below this answer for whether or not this is a better idea than the OP's original code.
Upvotes: 1