Search code examples
listprologinstantiation-error

Prolog - Arguments are not sufficiently instantiated. lists/recursion


I am trying to get the maximum number from a given list 'L' and assign it to a variable, so I used to write the following function:

max(L,X):-
    [H|Q]=L,
    (X<H -> X=H),
    length(Q,QLEN),
    (QLEN>0 -> max(Q,X)),
    true.

However after compiling the code and prompting max([1,2,3],X) within SWI-Prolog, I get the following error:

ERROR: Arguments are not sufficiently instantiated ERROR: In: ERROR:
[9] _1064<1 ERROR: [8] max([1,2|...],_1092) at c:/users/kais/desktop/tp3.pl:24 ERROR: [7]

Why I'm getting such error?


Solution

  • As said in the comment you try to compare H with X which is not instantiated. A solution to this problem is to create a predicate maxList/3 and call it inside maxList/2 as follows:

    maxList([H|T], Max) :-
        maxList(T, H, Max).
    
    maxList([], Max, Max).
    maxList([H|T], Max0, Max) :-
        Max1 is max(H, Max0),
        maxList(T, Max1, Max).
    
    ?- maxList([1,2,3],X).
    X = 3.
    

    max/2 simply returns the max between two arguments. A possible implementation for max/2 could be:

    myMax(M,A,B):-
        A > B ->  M = A;
        M = B.
    
    ?- myMax(A,1,2).
    A = 2.
    

    BTW, there is already a built in predicate in SWI to do this, which is called max_list/2 (the code I posted before actually comes from this implementation):

    ?- max_list([1,2,3],X).
    X = 3.