2

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.

false
  • 10,264
  • 13
  • 101
  • 209
Nicholas Hubbard
  • 527
  • 2
  • 15

1 Answers1

2

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.

David Tonhofer
  • 14,559
  • 5
  • 55
  • 51
  • 2
    findall/3 has some subtle problems (Richard O'Keefe's "Craft of Prolog" describes them); I would suggest bagof/3 or setof/3. Also, watch out for free variables. Some edge cases are mentioned here: https://swi-prolog.discourse.group/t/findall-3-and-overlapping-use-of-variable-names/3309 – Peter Ludemann Dec 02 '20 at 19:55
  • 1
    @PeterLudemann Thanks Peter. I wrote them up here: [About findall/3](https://github.com/dtonhofer/prolog_notes/tree/master/swipl_notes/about_findall). I actually didn't look at O'Keefe's book. I shall take a look. – David Tonhofer Dec 02 '20 at 20:00