- •Предисловие
 - •Глава 1 Введение в Пролог
 - •Глава 2 Синтаксис и унификация
 - •2.1. Синтаксис термы
 - •Константы
 - •Переменные
 - •Область действия переменных
 - •Сложные термы, или структуры
 - •Синтаксис операторов
 - •Синтаксис списков
 - •Синтаксис строк
 - •Утверждения
 - •Запросы
 - •Ввод программ
 - •2.2 Унификация
 - •Глава 3 Арифметические выражения
 - •3.1. Введение
 - •3.2. Арифметические выражения
 - •3.3. Арифметические операторы
 - •3.4. Вычисление арифметических выражений
 - •3.5. Сравнение результатов арифметических выражений
 - •Глава 4 Рекурсия
 - •4.1. Стратегия «разделяй и властвуй»
 - •Пример 4.1.1
 - •Фаза разбиения
 - •Фаза решения задачи
 - •4.2. Восходящая стратегия
 - •4.3. Рекурсия и эффективность
 - •Пример 4.3.2
 - •Глава 5 Структуры данных
 - •5.1. Списки списковая форма записи
 - •А на запрос
 - •Некоторые стандартные целевые утверждения для обработки списков
 - •5.2. Бинарные деревья представление бинарных деревьев
 - •Бинарное дерево на рис.5.2.1 имеет левое поддерево
 - •Представление множеств с помощью бинарных деревьев
 - •Будем называть линейным представление такого вида, как на рис.5.2.3, и сбалансированным - такое, как на рис.5.2.2.
 - •Левому поддереву соответствует отсортированный список
 - •Глава 6 Операторы
 - •6.1. Операторы и структуры синтаксис операторов
 - •Свойства операторов
 - •6.2. Позиция операторов
 - •6.3. Приоритет операторов
 - •6.4. Ассоциативность операторов
 - •6.5. Спецификаторы
 - •6.6. Операторы объявления
 - •6.7. Пример: вычисление многочленов
 - •6.8. Системные операторы
 - •Глава 7 Механизм возврата и процедурная семантика
 - •7.1. Механизм возврата
 - •7.2. Пример: задача поиска пути в лабиринте
 - •Целевое утверждение не удается согласовать с первым утверждением
 - •Если мы введем
 - •Если затем мы введем
 - •7.3. Обработка фактов с помощью механизма возврата
 - •7.4. Предикат repeat
 - •7.5. Декларативная и процедурная семантики
 - •Характеристики процедуры
 - •7.6. Вопросы эффективности
 - •Глава 8 Отсечение
 - •8.1. Почему используют отсечение?
 - •8.2. Использование отсечения
 - •Выдав запрос
 - •Обратившись к системе с запросом
 - •8.3. Ловушки отсечения
 - •Глава 9 Встроенные предикаты
 - •9.1. Встроенные предикаты
 - •9.2. Обновление базы данных Пролога
 - •Добавление и удаление утверждений
 - •Считывание утверждений в базу данных
 - •Предикаты сохранения и восстановления
 - •9.3. Особенности ввода и вывода чтение символов
 - •Запись символов
 - •Считывание термов Предикаты
 - •Запись термов
 - •9.4. Обработка файлов
 - •Редактирование программ на прологе
 - •Распечатка предикатов
 - •Глава 10 Модули. Пример разработки системы
 - •10.1. Модули
 - •Пример 10.1.1
 - •10.2. Пример разработки системы: деревья решений
 - •Описание дерева решений
 - •Разработка системы
 - •Целевое утверждение
 - •Глава 11 Отладка
 - •11.1. Трассировка
 - •Включение и выключение механизма трассировки
 - •Необязательные параметры трассировки
 - •Предикаты трассировки
 - •Режимы трассировки
 - •11.2. Установка контрольных точек
 - •Возможные действия в контрольной точке
 - •Включение и выключение режима контрольных точек
 - •Необязательные параметры режима контрольных точек
 - •Предикаты для работы с контрольными точками
 - •Режимы, связанные с контрольными точками
 - •Основные отладочные предикаты
 - •Статистическая информация
 
6.2. Позиция операторов
Позиция оператора в выражении определяет его тип. Как было сказано выше, оператор может относиться к одному из трех типов.
Инфиксный - оператор располагается между двумя аргументами, например: X+Y или Х < Y.
Префиксный - оператор располагается перед единственным аргументом, например: not Х или - X.
Постфиксный - оператор располагается после единственного аргумента, например: Х факториал или Р прошло.
6.3. Приоритет операторов
Каждый оператор имеет приоритетный номер, указываемый при объявлении оператора. Номер является целым числом и обычно находится в пределах от 1 до 1500.
Если выражение содержит более одного оператора, например
X + Y * 2,
то возникает неопределенность в порядке выполнения операций. Эта проблема разрешается посредством назначения всем операторам приоритетного номера. Вычисления осуществляются, начиная с оператора, имеющего наименьший номер, и заканчивая оператором с наибольшим номером. В нашем примере Х + Y * 2 оператор * имеет более низкий приоритетный номер, чем оператор +. Поэтому, как и следовало ожидать, выражение вычисляется так: Х + (Y * 2).
Тео戲етический приоритетный номер скобок меньше нуля. Выражение, заключенное в скобки, рассматривается как один терм. Скобки могут использоваться для того, чтобы изменить правила установления ассоциативности и сделать синтаксис выражений более четким.
6.4. Ассоциативность операторов
Ассоциативность оператора указывает, как следует интерпретировать выражение, содержащее несколько операторов с одинаковым приоритетом. Покажем на примере необходимость такой информации.
Рассмотрим выражение а/b/с. Результат его вычисления зависит от расстановки скобок:
(а/b)/с или а/(b/с)
Арифметические операции +, -(минус), * и / определены в Прологе как левоассоциативные. Это означает, что они должны иметь слева операторы равного или низшего приоритета, а справа - операторы строго низшего приоритета.
Следовательно, приведенное выше выражение в соответствии с правилом можно вычислить только как (а/b)/с, а не как а/(b/с).
6.5. Спецификаторы
Позицию и ассоциативность оператора удобно задавать с помощью спецификатора. Перечислим виды спецификаторов:
fx для определения постфиксного оператора;
fv “”
xf для определения префиксного оператора;
yf “”
xfx для определения инфиксного оператора;
xfy “” (правоассоциативного оператора);
yfx “” (левоассоциативного оператора);
yfy “”
В такой форме записи приняты следующие соглашения:
f представляет оператор. Им может быть системный оператор или оператор, объявленный с помощью предиката ор;
х представляет выражение, содержащее операторы только низшего приоритета по отношению к приоритету f;
у представляет выражение, которое может содержать операторы равного или низшего приоритета по отношению к приоритету f.
Если оператор объявлен со спецификатором yfx, то он является левоассоциативным и подвыражение у вычисляется первым. Возьмем в качестве примера
5 + 4 * 10 / 5.
Здесь операторы * и / имеют одинаковый приоритет, но, поскольку они определяются в Прологе как левоассоциативные, выражение будет вычисляться следующим образом:
y f х
(5+4*10) / 5
(5+(4*10)) / 5
Следовательно, (5+(4*10))/5 равно 9, если использовать правило определения приоритета.
Если оператор объявлен со спецификатором xfy, то он является правоассоциативным и подвыражение у, стоящее справа, вычисляется первым.
Спецификатор yfy недопустим в Прологе, так как выражения, содержащие операторы с такой ассоциативностью, окажутся неопределенными. Если бы * и / были объявлены со спецификаторами yfy, тогда выражение из предыдущего примера 5+4*10/5 можно было бы вычислить либо как прежде
(5+(4*10))/5=9,
либо как
5+(4*(10/5))=13
(суммирование + объявлено с большим приоритетом, чем * или /).
Применение спецификатора xfx в Прологе допустимо. Он используется, например, при объявлении операторов сравнения, таких, как < и >. Обычно трудностей не возникает, так как для операторов < и > в Прологе определяется более высокий приоритет, чем для арифметических операторов. Следовательно, правая и левая части выражения должны быть вычислены до того, как будет произведена попытка выполнить функцию сравнения, например,
5+2 < 6+3
будет вычисляться как
(5+2) < (6+3)
Однако существует возможность построить синтаксически правильное выражение, которое не подчиняется потенциально неопределенным правилам установления приоритета и ассоциативности.
Примером может служить выражение Х opr Y opr Z, где оператор opr имеет позицию и ассоциативность xfx.
В тех случаях, когда приоритет и ассоциативность не определяют порядок вычисления операторов, в большинстве реализации Пролога первым выполняется оператор, стоящий слева.
Поэтому предыдущее выражение будет вычислено следующим образом:
(а opr b) opr c.
Если * > объявлен как левоассоциативный, а < * - как правоассоциативный оператор с помощью управляющих команд (директив)
?- op(60,yfy,*>).
?- op(60,xfy,<*).
то выражение а*>b*>с вычисляется как (а*>b)*>с, а<*b<*с вычисляется как а<*(b<*с) и а<*b*>с вычисляется как (а<*b)*>с по умолчанию.
Некоторые реализации Пролога в таких неясных случаях выдают сообщение об ошибке.
