В Турбо-Прологе имеются специальные встроенные предикаты для работы с динамической базой данных. Таковыми являются asserta, assertz, retract, retracrall, save, consult.
Предикаты asserta, assertz и retract позволяют занести факт в заданное место динамической БД и удалить из нее уже имеющийся факт.
Предикат asserta заносит новый факт в базу данных, располагающуюся в оперативной памяти компьютера (резидентная БД). Новый факт помещается перед всеми уже внесенными утверждениями данного предиката. Этот предикат имеет такой синтаксис:
asserta(Clause)
Таким образом, чтобы поместить в БД утверждение о новом члене партии перед уже имеющимся там утверждением (стоящим в настоящий момент в базе данных на первом месте), необходимо следующее предикатное выражение:
asserta(member_party(”Кузьмич”,65,10,”y”))
Предикат assertz так же, как и asserta, заносит новые утверждения в базу данных. Однако он помещает новое утверждение за всеми уже имеющимися в базе утверждениями того же предиката. Синтаксис предиката столь же прост:
assertz(Clause)
Предикат retract удаляет утверждение из динамической БД. Его синтаксис таков:
retract(Existing_clause)
Если в базе данных НЕТ УТВЕРЖДЕНИЯ, которое вы пытаетесь удалить, то retract ОКОНЧИТСЯ НЕУДАЧЕЙ.
Предположим, что вы хотите удалить из базы данных второе утверждение. Для этого необходимо написать выражение:
retract(member_party(”Кузьмич”, 65,10,”y”))
Если вы хотите удалить из БД всех членов, не уплативших взносы, то можно воспользоваться предикатом:
retractall(member_party(_,_,_,”n”))
Предикат retractall ВСЕГДА УСПЕШЕН, даже при попытке удалить что-то из абсолютно пустой БД.
Предикат retract имеет важную особенность — он ПЕРЕДОКАЗЫВАЕТСЯ ПРИ ВОЗВРАТАХ (в отличие от asserta, assertz и retractall). Поэтому при применении предиката retract существует опасность непредсказуемого изменения программы. В дальнейшем будут рассмотрены приемы, позволяющие решить эту проблему.
Для модификации базы данных можно использовать комбинацию выражений с предикатами asserta, assertz и retract. Например, для того, чтобы отредактировать содержащееся в БД утверждение, ваша программа должна получить данные от пользователя, составить новое утверждение, удалить старое и занести новое.
Процедурой занесения в динамическую БД информации из статической БД, представляющей собой утверждения предиката member_party служит:
assert_database :-
member_party(Name,Age,Pay,Payment),
assertz(dmember_party(Name,Age,Pay,Payment)),
fail.
assert_database :- !.
Первое правило с помощью возврата после неудачи перебирает все утверждения предиката member_party, второе обеспечивает успешное завершение цели.
Процедура очистки динамической БД перед выходом из программы:
clear_database:-
retractall(dmember_party(_,_,_,_)).
Содержимое динамической БД можно и сохранить в файле на диске, и загрузить из файла.
Предикат save сохраняет находящуюся в оперативной памяти базу данных в текстовом файле. Синтаксис этого предиката:
save(DOS_file_name)
Здесь DOS_file_name есть произвольное допустимое в MS DOS имя файла.
Для того чтобы сохранить содержимое БД в файле текущего каталога с именем party.dba, требуется предикат:
save("party.dba")
Если файл с таким именем уже имелся на диске, то этот старый файл будет затерт, если такого файла не было, будет образован новый.
Файл с динамической БД представляет собой обычный текстовый файл, в котором утверждения сгруппированы по шаблону (если в БД имеется несколько разных предикатов), и каждое утверждение находится на отдельной строчке.
Файл БД может быть считан в память при помощи предиката consult, систаксис которого таков:
consult(DOS_file_name)
Для загрузки файла партийной БД требуется выражение consult("party.dba").
Следует помнить, что предикат consult неуспешен, если файл с указанным именем отсутствует на диске, или этот файл содержит ошибки, как, например, в случае несоответствия синтаксиса предиката из файла описаниям из раздела программы database, или если содержимое файла невозможно разместить в памяти ввиду отсутствия места.
Кроме того, при указании пути для любых предикатов, работающих с файлами обратный слэш \ следует заменять его кодом \92:
save(”a:\92dbs\92party.dba”)
Предикат findall позволяет собрать все имеющиеся в базе данные в список, который может быть полезен при дальнейшей работе. (Предикат findall был описан в гл. 7.) Так, findall можно использовать для получения списка имен всех членов партии. После того, как успешным будет предикат
findall(Name,dmember_party(Name,_,_,_),Name_list)
переменная Name_list будет содержать список всех имен.