Prolog:摆脱递归助手谓词

时间:2012-11-15 16:52:58

标签: prolog predicate logic-programming

所以我试图通过直接在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).

1 个答案:

答案 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的原始代码更好。