prologcomputer-scienceunificationdeclarative-programming

Member in combination with recursion


I learn Prolog at university and keep stumbling on someting rather odd during the home excercises. I wrote following Prolog clauses, which are part of a much bigger program:

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).

Which use following facts:

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

You can see highway as a fact that describes two nodes in the first two arguments and an edge in the third. All facts together form a connected graph.

With the clause edgesList, I want to list the edges per node e.g.

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

But when I write my query:

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

I get following result:

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

For some reason, Prolog won't unify the tail of the result-list with the empty list, despite the fact that the member-predicate is used correct, I assume. It's something that happend a few times now in different excercises and it would be good to know what I did wrong...


Solution

  • The problem is in the clause:

    edgesList([],_).
    

    because in the end it will fill the list with an uninstantiated tail (|_G610).

    One solution is :

    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).