Search code examples
listrecursionprologpredicateempty-list

How to deal with an empty list when finding last elements in a list of lists in Prolog?


I have a list of lists in Prolog. I've written a predicate that can find the last elements given a list such as this one:

L = [[a,b],[c,d,e],[f,g]]

This is the code, where the last_in_list/2 predicate just finds the last element in a simple list:

last_in_lol([], []).
last_in_lol([H|T], [X|Y]) :- last_in_list(X, H), append([],[X],L), last_in_lol(T, Y).

This seems to work just fine, outputting:

last_in_lol(L, F).
F = [b,e,g]

However, this fails when I give it a list which contains an empty list, like the following:

L = [[], [p,q,r], [s,t]]

I'm not sure how to go about augmenting my original predicate to handle this type of scenario. At the moment, this returns as False:

last_in_lol(L, F).
False.

I'd like it to return the list:

F = [r,t]

Solution

  • Can use head-and-tail notation:

    last_in_lol([], []).
    last_in_lol([[]|R], Y) :-
        last_in_lol(R, Y).
    last_in_lol([[H|T]|R], [Last|Y]) :-
        last_elem([H|T], Last),
        last_in_lol(R, Y).
    
    last_elem([H|T], Elem) :-
        last_elem_(T, H, Elem).
    
    last_elem_([], Elem, Elem).
    last_elem_([H|T], _, Elem) :-
        last_elem_(T, H, Elem).
    

    Results in swi-prolog:

    ?- L = [[a,b],[c,d,e],[f,g]], last_in_lol(L, F).
    L = [[a, b], [c, d, e], [f, g]],
    F = [b, e, g].
    
    ?- L = [[], [p,q,r], [s,t]], last_in_lol(L, F).
    L = [[], [p, q, r], [s, t]],
    F = [r, t].