
- •Глава 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"
- •Библиографические заметки
- •Упражнения
Влияние предиката "сократить" на процедуру
Предположим, что интерпретатор возвращается назад через множество фраз, образующих процедуру. В теле одной из фраз находится предикат "сократить". Если интерпретатор дойдет до этого предиката, то он не сможет вернуться далее назад для рассмотрения остальных фраз данного множества.
Процедура "а", в которой не используется предикат "сократить"
Рассмотрим в качестве примера два варианта процедуры "а" - с использованием и без использования предиката "сократить". Если этот предикат не употребляется, то процедура "а" определяется следующим образом:
а (1): -
write ('один').
а (Х): -
d (X),
write ('два').
а (3): -
write ('три').
d ('2a').
d ('2b').
Запрос к процедуре "а" даст такие ответы:
|? -a (N)
один
N=1;
два
N=2a;
два
N=2b;
три
N=3;
нет
В точке выдачи второго ответа состояние интерпретатора будет таким:
- Активные запросы - — Фразы программы —
а (1): -
write ('один').
?-а('2а'). ——--> а('2a'): -
d('2а'),
write('двa').
а (3): -
write ('три').
? -d ('2a'). --------> d ('2a').
d ('2b').
Процедура "а1", в которой используется предикат "сократить "
В другой версии процедуры "а", названной "а1", в середине второго правила расположен предикат "сократить":
а1 (1): -
write ('один').
а1 (Х): -
d (X),
!, % сократить
write ('два').
а1 (3): -
write ('три').
d ('2a').
d ('2b').
Посмотрим, что получится, если интерпретатор будет обрабатывать такой запрос к процедуре "а1 ":
|? -a1 (N).
один
N=1;
Если пользователь введет символ ; , то интерпретатор возвратится назад и начнет обрабатывать тело второго правила процедуры "а1". Подцель "d" конкретизирует переменную Х значением 2а, интерпретатор проходит предикат "сократить", а затем подцель "write" выводит слово «два» на экран дисплея:
два
N=2a;
Поведение интерпретатора при выдаче первых двух ответов, показанных выше, является точно таким же, как и при выдаче ответов на запрос к процедуре "а". Действие предиката "сократить" пока еще не проявилось. Но посмотрим, что получится, если пользователь захочет получить третий ответ. Интерпретатор попытается возвратиться назад от подцели «write ('два')». Однако из-за влияния предиката "сократить" на составной запрос интерпретатор не может вернуться обратно к подцели "d (X)" для получения нового значения переменной X. А вследствие действия предиката "сократить" на множество фраз программы интерпретатор не будет рассматривать третье правило процедуры "а1". Поэтому больше не будет получено позитивных ответов, и интерпретатор выдаст сообщение:
нет
Итак, из-за действия предиката "сократить" состояние интерпретатора после второго ответа будет таким:
- Активные запросы - - Фразы программы -
а1 (1): -
write ('один').
а1 (Х): -
d (X),
!,
write ('два').
al (3): -
write ('три').
? -a1 (N). ——--->
d ('2a').
d ('2b').
? -d (X). ----——>
Предикат "сократить" как подцель в составном запросе
Приведем несколько примеров, иллюстрирующих применение предиката "сократить". Если предикат "сократить" будет последней подцелью составного запроса, то это будет гарантировать получение только одного ответа на данный запрос:
|?—дядя (джон, W),!.
W = даниэль;
нет