成员结合递归

Member in combination with recursion

我在大学学习 Prolog,但在家庭练习中不断遇到一些相当奇怪的问题。我写了以下 Prolog 子句,它们是更大程序的一部分:

edges(X,Edges):-
    findall(Edge,(highway(X,Y,Edge);highway(Y,X,Edge)),Edges).

edgesList([],_).
edgesList([node(X)|InL],OutL):-
    member((node(X),Edges),OutL),
    edges(X,Edges),
    edgesList(InL,OutL).

其中使用了以下事实:

highway(1,2,yellow). 
highway(2,3,blue). 
highway(1,3,yellow).

您可以将高速公路视为一个事实,它在前两个参数中描述了两个节点,在第三个参数中描述了一条边。所有的事实一起形成一个连通图。

使用 edgesList 子句,我想列出每个节点的边,例如

Result = [(node(1),[yellow,yellow]),(node(2),[blue,yellow]),(node(3),[blue,yellow])]

但是当我写查询时:

edgesList([node(1),node(2),node(3)],List).

我得到以下结果:

List = [(node(1),[yellow, yellow]), (node(2),[blue, yellow]), (node(3),[blue, yellow])|_G610]

出于某种原因,Prolog 不会将结果列表的尾部与空列表统一起来,尽管我认为成员谓词的使用是正确的。这是现在在不同练习中发生过几次的事情,很高兴知道我做错了什么......

问题出在子句中:

edgesList([],_).

因为最后它会用未实例化的尾巴(|_G610)填充列表。

一个解决方案是:

edges(X,Edges):-
    findall(Edge,(highway(X,Y,Edge);highway(Y,X,Edge)),Edges).

edgesList([],[]).
edgesList([node(X)|InL],[(node(X),Edges)|T]):-
   edges(X,Edges),
   edgesList(InL,T).