- •Глава 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"
- •Библиографические заметки
- •Упражнения
Автоматический просмотр выполнения программы
Во всех версиях языка Пролог имеются отладочные средства, предоставляющие возможность пользователю наблюдать за работой интерпретатора при выполнении запроса. Эти средства будут различными в разных версиях языка. Поэтому для того, чтобы выяснить, какие отладочные средства есть в Вашей версии Пролога и как этими средствами пользоваться, следует обратиться к руководству по Вашей версии Пролога или к приложению IV данной книги. Если отладочные средства Вашей версии Пролога слишком слабы, то можно воспользоваться программой из гл. 7, которая называется "вид" (сокращение от "видимый Пролог"). Эта программа обеспечивает выдачу весьма подробной отладочной информации. Итак, если Вам необходимо точно знать, что делает интерпретатор при выполнении запроса (т. е. если требуется узнать, где он начинает делать не то, что хочет программист, или узнать, не тратит ли интерпретатор время впустую), то можно:
1) построить подробные диаграммы активных запросов (аналогичные диаграммам из данной главы), которые описывают действия, предпринимаемые интерпретатором;
2) воспользоваться отладочными средствами Вашего интерпретатора для наблюдения за ходом выполнения программы; или
3) ввести программу "вид" из разд. 7, 3 и использовать ее для наблюдения за ходом выполнения программы.
3.2. Предикат "сократить" Пространство поиска запроса
Пространство поиска запроса - это множество всех возможных ответов, рассматриваемых интерпретатором при выполнении запроса. В предыдущем разделе были полностью исследованы пространства поиска запросов к правилам "дядя" и "регистрация". Ясно, что часть пространства поиска запроса "регистрация" - когда интерпретатор пытается найти второй возраст Брайена — не влияет на способность программы находить правильные ответы. Эту часть пространства поиска можно отбросить с целью повышения эффективности работы программы.
Предикат "сократить" останавливает возврат назад
Существует специальный встроенный предикат "сократить" (записывается как символ !), который дает указание интерпретатору не возвращаться назад далее той точки, где стоит этот предикат. Предикат "сократить" применяется главным образом для уменьшения размера пространства поиска запроса. Этим предикатом, однако, следует пользоваться с осторожностью. Он не имеет четкого декларативного смысла (т. е. он всегда будет истинным), поэтому при употреблении данного предиката будет наноситься некоторый ущерб понятности программы. Наличие предиката "сократить" может непредвиденным образом нарушить работу программы.
Предикат "сократить" по-разному действует на составной запрос и на множество фраз, образующих процедуру. Эти два вида действия предиката четко различаются между собой.
Влияние предиката "сократить" на составной запрос
Рассмотрим случай, когда предикат "сократить" является одной из подцелей составного запроса. После того как интерпретатор пройдет предикат "сократить", он больше не сможет возвратиться назад к подцелям, стоящим перед этим предикатом. Таким образом, предикат "сократить" действует так, что интерпретатор обязан использовать те значения переменных, расположенных слева от предиката, которые они получили при конкретизации.
Пример составного запроса с предикатом "сократить":
|? -a (X), b (Y),!, c (X, Y, Z).
При выполнении данного запроса интерпретатор пройдет через предикат "сократить" только в том случае, если и подцель а (Х), и подцель b (Y) окажутся успешными. После того как предикат "сократить" будет обработан, интерпретатор не сможет возвратиться назад для повторного рассмотрения подцелей "а" и "b", если подцель "с" потерпит неудачу при текущих значениях переменных Х и Y.
Этот составной запрос не обладает декларативным смыслом. При процедурном подходе, однако, его можно прочесть так:
Взять значение переменной Х из подцели "а"
и значение переменной Y из подцели "b ",
а затем выполнить подцель с (Х, Y, Z).