Search code examples
prologfailure-slice

Prolog not halting when implementing reverse list


This is my implementation:

popped_last_el([], [_]).
popped_last_el([F | R], [F | X]) :- popped_last_el(R, X).

last_el(X, [X]).
last_el(X, [_ | L]) :- last_el(X, L).

reverse_list([], []).
reverse_list([F | R], L2) :- last_el(F, L2), popped_last_el(L, L2), reverse_list(R, L).

When I query reverse_list([a, b], X), it outputs X = [b, a] as expected. But when I ask for another solution using ;, prolog runs indefinitely. Why?


Solution

  • Why?

    Here is a to explain why the program still loops. Only this very tiny part of your program is responsible for non-termination. You will have to fix something in that part to make non-termination go away.

    last_el(X, [X]) :- false.
    last_el(X, [_ | L]) :- last_el(X, L), false.
    
    reverse_list([], []) :- false.
    reverse_list([F | R], L2) :-
       last_el(F, L2), false,
       popped_last_el(L, L2),
       reverse_list(R, L).
    
    ?- reverse_list([a, b], X), false.
       loops.
    

    What you can see from this failure-slice:

    L2 needs to be known ('instantiated') to make last_el/2 terminate. But it is not.