счетчик( _, [ ], 0).
счетчик( Терм, [Голова | L], N) :-
Терм == Голова, !,
счетчик( Терм, L, N1),
N is N1 + 1;
счетчик( Терм, L, N).
Назад | Содержание | Вперёд
Назад | Содержание | Вперёд
7. 4. Работа с базой данных
Реляционная модель предполагает, что база данных - это описание некоторого множества отношений. Пролог-программу можно рассматривать как именно такую базу данных: описание отношений частично присутствует в ней в явном виде (факты), а частично - в неявном (правила). Более того, встроенные предикаты дают возможность корректировать эту базу данных в процессе выполнения программ. Это делается добавлением к программе (в процессе вычисления) новых предложений или же вычеркиванием из нее уже
существующих. Предикаты, используемые для этой цели, таковы:
assert
(добавить),
asserta
,
assertz
и
retract
(удалить).
Цель
assert( С)
всегда успешна, а в качестве своего побочного эффекта вызывает "констатацию" предложения С, т. е. добавление его к базе данных.
Цель
retract( С)
приводит к противоположному эффекту: удаляет предложение, сопоставимое с С. Следующий диалог иллюстрирует их работу:
?- кризис.
no
? - assert( кризис).
yes
?- кризис.
yes
? - retract( кризис).
yes
?- кризис.
no
Предложения, добавленные к программе таким способом, ведут себя точно так же, как и те, что были в "оригинале" программы. Следующий пример показывает, как с помощью assertи retractможно работать в условиях изменяющейся обстановки. Предположим, что у нас есть такая программа о погоде:
хорошая :-
солнечно, not дождь.
необычная :-
солнечно, дождь.
отвратительная :-
дождь, туман.
дождь.
туман.
Ниже приводится пример диалога с этой программой, во время которого база данных постепенно изменяется:
?- хорошая.
no
?- отвратительная.
yes
?- retract( туман).
yes
?- отвратительная.
no
?- assert( солнечно).
yes
?- необычная.
yes
?- retract( дождь).
уes
?- хорошая.
yes
Добавлять и удалять можно предложения любой формы. Следующий пример показывает, что, кроме того, retractможет работать недетерминировано: используя механизм возвратов с помощью только одной цели retractможно удалить целое множество предложений. Предположим, что в программе, с которой мы "консультируемся", есть такие факты:
быстр( энн).
медл( том).
медл( пат).
К этой программе можно добавить правило:
?- assert(
( быстрее( X, Y) :-
быстр( X), медл( Y) ) ).
yes
?- быстрее( А, В).
А = энн
В = том
?- retract( медл( X) ).
Х = том;
X = пат;
nо
?- быстрее( энн, _ ).
nо
Заметьте, что при добавлении нового правила синтаксис требует, чтобы оно (как аргумент assert) было заключено в скобки.
При добавлении нового предложения может возникнуть желание указать, на какое место в
базе
данных его следует поместить. Такую возможность обеспечивают предикаты
asserta
и
assertz
. Цель
asserta( С)
помещает С в начале базы данных. Цель
assertz( С)
- в конце. Вот пример, иллюстрирующий работу этих предикатов:
?- assеrt( р( a)), assertz( р( b) ), asserta( p( c) ).
yes
?- p( X).
Х = с;
Х = а;
Х = b
Между consultи assertzсуществует связь. Обращение к файлу при помощи consultможно в терминах assertzопределить так: считать все термы (предложения) файла и добавить их в конец базы данных.
Одним из полезных применений предиката assertaявляется накопление уже вычисленных ответов на вопросы. Пусть, например, в программе определен предикат
решить( Задача, Решение)
Мы можем теперь задать вопрос и потребовать, чтобы ответ на него был запомнен, с тем чтобы облегчить получение ответов на будущие вопросы:
?- решить( задача1, решение),
asserta( решить( Задача1, Решение) ).
Если в первой из приведенных целей будет успех, ответ ( Решение)будет сохранен, а затем использован так же,
Читать дальше