Prolog:摆脱递归辅助谓词

Prolog:摆脱递归辅助谓词,prolog,predicate,logic-programming,Prolog,Predicate,Logic Programming,因此,我试图通过直接在split中使用sort库谓词来摆脱wrapper子句。split所做的只是从如下列表生成一个数字列表:[1:2,3:2,4:6]——split-->[1,2,3,2,4,6]。但是生成的列表包含重复项,我不希望这样,所以我使用包装器将拆分和排序结合起来,然后生成所需的结果:[1,2,3,4,6] 我真的很想去掉包装器,只在split中使用sort,但是我一直得到“ERROR:sort/2:Arguments-not-fully-instanced.”有什么想法吗?谢谢:)

因此,我试图通过直接在split中使用sort库谓词来摆脱wrapper子句。split所做的只是从如下列表生成一个数字列表:[1:2,3:2,4:6]——split-->[1,2,3,2,4,6]。但是生成的列表包含重复项,我不希望这样,所以我使用包装器将拆分和排序结合起来,然后生成所需的结果:[1,2,3,4,6]

我真的很想去掉包装器,只在split中使用sort,但是我一直得到“ERROR:sort/2:Arguments-not-fully-instanced.”有什么想法吗?谢谢:)

我真的很想去掉包装器,只使用split中的sort

然后将
findall
用于复杂的目标,例如

split(Edges, NodeSet) :-
    findall(Node,
            (member(Edge, Edges), (Edge = (Node:_); Edge = (_:Node))),
            NodeList),
    sort(NodeList, NodeSet).
但是,一旦开始使用聚合谓词,就可以跳过
排序
,使用
集合

split(Edges, NodeSet) :-
    setof(Node, Edge^Pair^(member(Edge, Edges),
                           Edge =.. [:|Pair],
                           member(Node,Pair)),
          NodeSet).
读作:获取所有
节点
s.t.存在
和存在
s.t.(等)的集合,并调用该
节点集

=..
(“univ”)操作符解构一对:
边=。。[:,左,右]
。为了更好的可读性,您可以编写一个单独的谓词来从边获取节点:

% 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的原始代码更好

我真的很想去掉包装器,只使用split中的sort

然后将
findall
用于复杂的目标,例如

split(Edges, NodeSet) :-
    findall(Node,
            (member(Edge, Edges), (Edge = (Node:_); Edge = (_:Node))),
            NodeList),
    sort(NodeList, NodeSet).
但是,一旦开始使用聚合谓词,就可以跳过
排序
,使用
集合

split(Edges, NodeSet) :-
    setof(Node, Edge^Pair^(member(Edge, Edges),
                           Edge =.. [:|Pair],
                           member(Node,Pair)),
          NodeSet).
读作:获取所有
节点
s.t.存在
和存在
s.t.(等)的集合,并调用该
节点集

=..
(“univ”)操作符解构一对:
边=。。[:,左,右]
。为了更好的可读性,您可以编写一个单独的谓词来从边获取节点:

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

术语
[1:2,3:2,4:6]
在我看来很奇怪,为什么?这是什么?
ins(T,NT)
?ins应该被递归地分割调用,我的坏:)。固定的。[1:2..]是图形中的边列表。使用
split/2
的定义,您永远不会收到该错误消息。那是不可能的!不清楚,你说的包装是什么意思。你从其他地方得到像[1:2,3:2]这样的数据,所以你必须处理它?否则我会推荐[1-2,3-2],因为有些库会采用这种表示法。不客气!也许你会学着喜欢它……这个词对我来说很奇怪,它是干什么用的?这是什么?
ins(T,NT)
?ins应该被递归地分割调用,我的坏:)。固定的。[1:2..]是图形中的边列表。使用
split/2
的定义,您永远不会收到该错误消息。那是不可能的!不清楚,你说的包装是什么意思。你从其他地方得到像[1:2,3:2]这样的数据,所以你必须处理它?否则我会推荐[1-2,3-2],因为有些库会采用这种表示法。不客气!也许你会学会喜欢它……与原来的
split/2
相比,你在这里得到了什么?除非存在变量,否则您的解决方案不起作用。@false:您仍然无法从包含变量的列表中找到一组元素。您得到的是,您现在有了一个或两个目标,您可以插入到更大子句的中间,而不必命名它们,因为递归现在是隐式的。这就是这些谓词存在的原因。(=..)/2?!?!这是70年代吗?:-)@false:你建议用什么来代替它?直接使用变量没有意义,但它们可能作为额外的参数出现。你确定这永远不会发生吗?我不太确定。与原来的
split/2
相比,您在这里得到了什么?除非存在变量,否则您的解决方案不起作用。@false:您仍然无法从包含变量的列表中找到一组元素。您得到的是,您现在有了一个或两个目标,您可以插入到更大子句的中间,而不必命名它们,因为递归现在是隐式的。这就是这些谓词存在的原因。(=..)/2?!?!这是70年代吗?:-)@false:你建议用什么来代替它?直接使用变量没有意义,但它们可能作为额外的参数出现。你确定这永远不会发生吗?我不太确定。