Search code examples
prologprolog-toplevel

Query returning true/false


I recently started learning Prolog and have come across an issue.

The following has been loaded into Prolog:

likes(john, apple).
likes(john, pear).
likes(john, grapes).
likes(bill, mango).
likes(bill, apple).

I am writing a predicate all_like(What, List) that should return True if all the people in List like the fruit in What.

Eg:

all_like(apple,[john, bill]).

should return:

true ;
false.

all_like(grapes,[john, bill]).

should return:

false.

I have the following code:

all_like(What,List) :- check_list(What,List).

check_list(What,[]) :- write('true').
check_list(What, [X|Rest]) :- likes(X,What), check_list(What,Rest).
check_list(What, [X|Rest]) :- \+ likes(X,What), write('false').

My results are:

1st Query

true
true .

2nd Query

false
true .

Would anyone know why I'm getting these results?

What is the significance of the second boolean value being outputted?

Finally, is the . appearing after a space of significance?

Thank you for your help.


Solution

  • Prolog already indicates whether a predicate succeeds (true or yes) or fails (false or no), so you're doing too much work in your predicate when you (a) explicitly write out "true" on success, and (b) you try to succeed on a failure case and write out failure. It's best to let the failing case just fail, then Prolog will show the failure.

    As an aside, your check_list predicate is superfluous and you can just use all_likes. So this is really all you need:

    all_likes(_, []).             % An empty list likes anything
    all_likes(What, [X|Rest]) :-  % All of [X|Rest] likes What if... 
        likes(X, What),           % X likes What and...
        all_likes(What, Rest).    % All of Rest likes What
    

    In SWI Prolog, you'll see these results:

    ?- all_likes(apple,[john, bill]).
    true ;
    false.
    
    ?- all_likes(grapes,[john, bill]).
    false.
    

    In GNU Prolog, the output looks like this:

    | ?- all_likes(apple,[john, bill]).
    
    true ? ;
    
    no
    | ?- all_likes(grapes,[john, bill]).
    
    no
    | ?-