Search code examples
prologunification

Prolog: why this predicate finds the answer but ignores it and goes on to unify with []?


I wrote a predicate that is supposed to traverse through a list of numbers and compare current number to the next one then adds the bigger number to a list that it is supposed to return. The last number is simply added to the list.

For example:

[1,2,3] should return [2,3,3]

[3,5,6,6,5,9] should return [5,6,6,6,9,9]

Problem

The predicate finds the answer (it writes it out), but it doesn't unify(?) with it and goes on to return [].

Code:

head([H|_], H).
head([],[]).

maximize([], X) :- write(X).
maximize([H|T], X) :-
    (head(T, N), N = []) -> (append(X, [H], L), maximize([], L)) ;
    (head(T, N), H < N) -> (append(X, [N], L), maximize(T, L)) ; (append(X, [H], L), maximize(T, L)).

Solution

  • A solution for the problem you describe is:

    maximize([], []).
    maximize([X| Xs], M) :-
        maximize(Xs, X, M).
    
    maximize([], X, [X]).
    maximize([Y| Ys], X, M) :-
        (   Y > X ->
            M = [Y| T]
        ;   M = [X| T]
        ),
        maximize(Ys, Y, T).
    

    Sample calls:

    | ?- maximize([1,2,3], M).
    
    M = [2,3,3]
    yes
    
    | ?- maximize([3,5,6,6,5,9], M).
    M = [5,6,6,6,9,9]
    yes
    

    This solution takes advantage of first-argument indexing to avoid spurious choice points.