Не используйте findall/3
для этого. Это прекрасный пример того, как bagof/3
и setof/3
отличаются от findall/3
.
Ваш пример немного странный, так что вот еще одна база данных. Я удалил первый аргумент, потому что вы, кажется, его не используете, и добавил больше строк, чтобы их можно было различать по возрасту. Обратите внимание, что нет смысла иметь свободные переменные в таблице фактов, например person
, поэтому все строки имеют значения в обеих позициях.
person(abel, 20).
person(bill, 30).
person(clive, 20).
person(diana, 10).
person(evan, 200).
person(fia, 20).
people_age(Age, Ps) :-
bagof(P, person(P, Age), Ps).
С этим определением people_age/2
, вы можете запросить, например:
Кто люди в возрасте от 20?
?- people_age(20, Ps).
Ps = [abel, clive, fia].
Группа людей по их возрасту.
?- people_age(Age, Ps).
Age = 10,
Ps = [diana] ;
Age = 20,
Ps = [abel, clive, fia] ;
Age = 30,
Ps = [bill] ;
Age = 200,
Ps = [evan].
Кто, по крайней мере 30 лет?
?- people_age(Age, Ps), Age >= 30.
Age = 30,
Ps = [bill] ;
Age = 200,
Ps = [evan].
Последняя можно было бы сделать по-другому, если вы не хотите, чтобы группы по возрасту.Вот как:
?- bagof(P, Age^(person(P, Age), Age >= 30), Ps).
Ps = [bill, evan].
или, может быть,
?- bagof(Age-P, Age^(person(P, Age), Age >= 30), Ps).
Ps = [30-bill, 200-evan].
... если вы не хотите, чтобы выбросить возраст полностью.
Но вы должны просто прочитать «сбор всех решений в Прологе» и предполагаемое использование всех трех: findall/3
, bagof/3
, setof/3
.
Существует проблема с тем, как вы решили организовать свои данные. У вас есть аргумент для ID, но в вашем примере вы оставляете эти «анонимные». Вместо этого вы можете нормализовать свою базу данных и просто иметь «id_name/2» и «id_age/2», например (я не знаю, что вы пытаетесь моделировать, хотя ... может ли человек иметь имя и возраст, но нет ID? Или имя или возраст неизвестны? В любом случае, нормализуя базу данных и просто оставляя строки для деталей, которые вы не знаете, намного чище, что оставляет «дыры» в таблице.) –
PS: и, конечно, вам нужен «первичный ключ», и обычно идентификатор играет роль первичного ключа. Но поскольку вы оставили код в двух строках, которые у вас есть в вашем примере, я немного смущен. Конечно, это очень плохой первичный ключ. –