Say I have these facts:
person(fred).
person(jim).
person(mary).
is_person(person(_)).
I would like to get a list like:
[person(fred), person(jim), person(mary)]
but my query with findall/3
does not give the expected result:
?- findall(Person,is_person(Person),ListOfPeople).
ListOfPeople = [person(_5034)].
Similarly with bagof/3
:
?- bagof(Person,is_person(Person),ListOfPeople).
ListOfPeople = [person(_5940)].
I do not understand why findall/3
and bagof/3
behave like this.
The correct way:
findall(person(Person),person(Person),ListOfPeople).
or
bagof(person(Person),person(Person),ListOfPeople).
Why doesn't your approach work? Consider
findall(Person,is_person(Person),ListOfPeople).
Prolog tries to fulfill is_person(Person)
.
There is a fact is_person(person(_)).
So, for Person = person(_)
, we are good! So person(_)
will be in the list.
And that's all, there are no other ways to derive is_person(Person)
.
To collect all the Person
, we really need to ask for the Person
which fulfills person(Person)
.
Thus:
findall(person(Person),person(Person),ListOfPeople).
Prolog will find three Person
which fulfill person(Person)
. As the result should not be a list of Person
but of person(Person)
we slap a person/1
around Person
in the 1st parameter, the template.
Alternatively (but a bit pointlessly), you could:
is_person(person(X)) :- person(X).
?- findall(X,is_person(X),ListOfPeople).
Here, Prolog collects all the X
for which is_person(person(X))
, which are all the X
which appear in a (fact) person(X)
. Thus X
is for example fred
. We slap a person/1
around fred
in the head of is_person/1
. Done.