Search code examples
variablesprologsingletonprolog-setofprolog-findall

Correct use of findall/3, especially the last result argument


I'm a beginner in Prolog and I am dealing with a problem that might seem stupid to you, but I really can't understand what I'm doing wrong! Ok, I have this file fruits.pl and inside that I have something like this:

fruit(apple,small,sweet).
fruit(lemon,small,nosweet).
fruit(melon,big,sweet).

I have already (inside that file made a coexist(X,Y) atom that checks if two fruits can be put together in a plate. It works fine! But now I can't create a suggest(X) that takes as a parameter a fruit and returns a list of fruits that can be put together in the same plate. The thing is I was trying to make something like that

suggest(X) :- findall(Y,fruit(Y,_,_), List), coexist(X,Y).

What do you think? Every time I try to run this in swi prolog there is a warning 'singleton variable' and when I press

suggest(apple).

then it says false.. sorry for my english :/


Solution

  • Predicates in Prolog do not return anything. You have goals that are satisfied or not and you can interpret that as returning true or false.

    Your predicate suggest(X) should contain another parameter that will be bound to the list of fruits that go together with X. An option would be: suggest(X, List) which describes the following relation: List represents all the fruits that go together with X. Then, you could ask:

    ?- suggest(apple, List).
    List = [pear, cherry].
    

    The goal findall(Y, ... , ...) uses the Y variable internally and Y is still unbound after the goal is satisfied. So, you should move coexist(X,Y) inside the second argument of findall/3 which is the goal that is satisfied in all possible ways. Th rule below works only if X is instantiated (suggest(+X, -List)).

    suggest(X, List) :- findall(Y, (fruit(Y,_,_), coexist(X, Y)), List).
    

    You can read this as follows: "List represents all fruits Y that coexist with X".