Иногда, при программировании определенных задач, возникает необходимость собрать данные из базы данных в список для последующей их обработки. Турбо-Пролог содержит встроенный предикат, позволяющий справиться с этой задачей без каких-бы то ни было хлопот. Таким предикатом является предикат findall. Требуемый список представляется означенной переменной, являющейся одним из объектов предиката.
Предописание встроенного предиката findall выглядит следующим образом:
Variable_name обозначает здесь объект входного предиката Predicate_expression, а List_name является именем переменной выходного списка. Переменная должна относиться к домену списков, объявленному в разделе domains.
Для пояснения только что сказанного, рассмотрим предикат male из программы 2.1 «РОДСТВЕННИКИ» главы 2.
Соберем в список всех мужчин рассматриваемой семьи. Вначале в разделе domains опишем соответствующий список:
domains
name = symbol
list = symbol*
и составим этот список Mlist с помощью предиката findall:
goal
findall(X, male(X), Mlist), write(Mlist).
Предикат findall может работать не только с фактами, но и с правилами. Соберем в список Slist всех сестер:
goal
findall(X, sister(X,_), Slist), write(Slist).
или всех сестер и братьев beth:
goal
findall(X,sister(beth,X),Blist), write(Blist).
Упражнение 7.2.
Собирите в список всех родственников бэт и удалите повторяющиеся элементы. Для удаления из списка кратностей запрограммируйте процедуру delcrat следующему алгоритму:
1. Пустой список — список без кратностей.
2. Если голова списка H принадлежит хвосту списка T (member(H,T)), то вызываем delcrat для хвоста списка.
3. Если голова списка H не принадлежит хвосту списка T, то H является головой целевого списка, а хвост целевого списка T’ получается после удаления кратностей из хвоста T: delcrat(T,T’).