- •Глава 3 управление ходом выполнения программы
- •3. 1. Как выполняется запрос в прологе
- •Три семантические модели
- •Выполнение запроса
- •Правила, описывающие унификацию термов
- •Пример с программой "дядя"
- •Активация запроса
- •Унификация запроса
- •Обработка тела фразы
- •Обработка подцели "брат"
- •Обработка подцели "отец"
- •Неудача запроса и возврат назад
- •Поиск третьего ответа
- •Поиск несуществующих ответов
- •Выполнение запроса к правилу "регистрация"
- •Автоматический просмотр выполнения программы
- •3.2. Предикат "сократить" Пространство поиска запроса
- •Предикат "сократить" останавливает возврат назад
- •Влияние предиката "сократить" на составной запрос
- •Влияние предиката "сократить" на процедуру
- •Предикат "сократить" как подцель в составном запросе
- •Использование предиката "сократить" для того, чтобы сделать процедуру детерминированной
- •Применение предиката "сократить" для отбрасывания части пространства поиска
- •Ограничение сферы действия предиката "сократить"
- •Общее правило ограничения сферы действия предиката "сократить"
- •3. 3. Отрицание как неудача запроса Негативная информация
- •Предположение о замкнутости мира
- •Тогда и только тогда, когда
- •Предположение об открытости мира
- •Отрицание в явной форме
- •Пример процедуры, поведение которой соответствует предположению об открытости мира
- •3. 4. Встроенные предикаты, предназначенные для обеспечения ввода-вывода Побочные эффекты ввода-вывода
- •Пример запроса, в котором используется предикат "read"
- •3. 5. Встроенные предикаты, предназначенные для управления файлами
- •3. 6. Проверка типа терма
- •Использование предикатов "var" и "nonvar"
- •3. 7. Действия с текущей программой
- •Изменение значения факта
- •Алгоритм поиска с возрастом, в котором используется предикат "assert"
- •Процедура, которая учится у пользователя
- •Программа, которая модифицирует сама себя
- •3. 8. Компараторы
- •3. 9. Прочие встроенные предикаты
- •Программа ввода "вводполя"
- •3. 10. Операции Расширяемость синтаксиса языка Пролог
- •Инфиксная операция ",", обладающая правой ассоциативностью
- •Инфиксная операция, не обладающая свойством ассоциативности
- •Объявление операций
- •3. 11. Преобразование процедурного алгоритма в программу на языке пролог Сравнение поиска с возвратом и рекурсии
- •Цикл "пока"
- •Рекурсия
- •Поиск с возвратом
- •Применение предиката "findall"
- •Библиографические заметки
- •Упражнения
Использование предикатов "var" и "nonvar"
Если воспользоваться предикатами "var" и "nonvar", то можно составить процедуру, выполняющую функции интерфейса для базы данных "возраст". Эта процедура накладывает ограничение, обеспечивающее целостность отношения, вида многие-к-одному во время выборки информации.
% Многие Один
возраст (бранен, 18).
возраст (майк, 17).
возраст (стив, 18).
% Возраст с ограничением многие-к-одному
мо_возраст (Имя, Возраст): - % (1)
nonvar (Имя),
возраст (Имя, Возраст),!. % сократить
мо_возраст (Имя, Возраст): - % (2)
var (Имя),
возраст (Имя, Возраст). % нет "сократить".
Если аргумент "Имя" в запросе к процедуре "мо_возраст" конкретизирован, то ответ на запрос будет получен по правилу (1). Предикат "сократить", расположенный в этом правиле после подцели "возраст", обеспечивает устранение бесполезных затрат времени на поиск еще одного значения возраста после определения первого значения этого параметра. С другой стороны, если аргумент "Имя" не конкретизирован, то ответ на запрос будет выдаваться в соответствии с правилом (2). В правиле (2) предикат "сократить" отсутствует, поэтому запрос может осуществить поиск с возвратом по всей базе данных "возраст". Проиллюстрируем это примерами.
|? - мо_возраст (бранен, X).
Х = 18, % ответ по правилу (1)
нет
|? - мо_возраст (Кто, 18).
Кто = брайен; % ответы по правилу (2) -
Кто = стив;
нет
Теперь можно написать новую версию процедуры "регистрация", которая получит название "регистрация 5". В ней используется процедура "мо_возраст". Запрос к процедуре "регистрация 5" всегда будет приводить к выдаче полного множества ответов без потери времени на бессмысленный поиск дополнительных значений возраста одного и того же лица. Применение процедуры "мо_возраст" позволяет сохранить модульность и базы данных "возраст", и процедуры "регистрация 5".
регистрация 5 (X): -
мужчина (X), мо_возраст (X, Y), Y=18.
|? - регистрация 5 (X).
X = брайен;
Х = стив;
Нет
3. 7. Действия с текущей программой
Существует ряд встроенных предикатов, позволяющих программными средствами изменять текущее множество фраз программы.
assert (X) Предикат "assert" ("принять") добавляет к текущей программе фразу X.
Пример:
|? - assert (король (людовик, франция)).
да
|? - король (людовик, X).
Х = Франция
asserta (X) Предикат "asserta" добавляет к текущей программе фразу Х как первую фразу процедуры.
assertz (X) Предикат "assertz" добавляет в текущую программу фразу Х как последнюю фразу процедуры.
retract (C) Предикат "retract" ("удалить") удаляет из текущей программы первую фразу, которая унифицируется с С. Предупреждение: предикат "retract" является средством деструктивного присваивания фраз, и пользоваться им следует с осторожностью.
Пример:
|? - retract (король (людовик, франция)).
да
|? — король (людовик, X).
нет
Изменение значения факта
Напишем короткую программу, в которой употребляются предикаты "assert" и "retract" для деструктивного присваивания значения факта, содержащего текущее время (в часах).
время (10).
изменить_время: —
время (Час), Нов_час is Час+ 1,
retract (время (Час)),
assert (время (Нов_час)).
При каждом запросе к процедуре "изменить—время" текущее время увеличивается на один час:
|? - изменить_время.
да
|? — время (X).
Х=11
|? -изменить_время.
да
|? — время (X).
Х=12