Списковая форма сводится к удобству записи, она не дает каких-либо дополнительных возможностей по сравнению с использованием предикатов consult и reconsult. Некоторые реализации Пролога могут использовать в списковой форме записи вместо знака '-' какой-нибудь иной знак, но эффект при этом останется прежним.
6.2. Выполнение и невыполнение целевого утверждения
При нормальном выполнении программы на Прологе целевое утверждение считается согласованным (с базой данных), когда это может быть доказано, и несогласованным в случае, когда доказательства найти не удается. В языке имеются два предиката, позволяющих удобно и явным образом определить случаи, когда целевое утверждение считается согласованным и когда несогласованным. Это предикаты true и fail.
Это целевое утверждение всегда согласуется с базой данных. В действительности этот предикат не является необходимым, так как утверждения в базе данных и цели могут быть переупорядочены или перегруппированы так, чтобы избежать использования предиката true. Однако для удобства он входит в состав встроенных предикатов.
Это целевое утверждение никогда не согласуется с базой данных. Имеются две ситуации, когда этот предикат оказывается полезным. Одна из них – это использование комбинации !- fail, которая уже была описана в разд. 4.3. Конъюнкция целевых утверждений
…!, fail
применяется для того, чтобы указать, что если процесс выполнения дошел до этого момента, то можно больше не пытаться доказать (согласовать) данное целевое утверждение. Конъюнкция считается несогласованной благодаря наличию предиката fail, а родительское целевое утверждение не согласуется ввиду того, что использовано отсечение.
Другая ситуация, в которой используется предикат fail, возникает, когда вы хотите явно указать, что для некоторого целевого утверждения нужно перебрать все решения. Возможно, вы захотите напечатать все возможные решения. Например, выполнение целевого утверждения
?- событие (X,Y), phh(Y), fail.
привело бы к печати всех событий, имеющихся в базе данных, рассмотренной в разд. 5.1, выбор событий и печать их краткого содержания выполняют предикаты событие и phh, при этом цель окажется несогласованной с базой данных. Еще одно применение fail рассмотрено в разд. 7.13 (в определении предиката retrac-tall).
6.3. Классификация термов
Если вам надо определить предикаты, которые будут использоваться с аргументами различных типов, то полезно иметь возможность выделять в определении предиката ситуации, соответствующие каждому из возможных типов. В простейшем случае может понадобиться применять разные утверждения в зависимости от того, является ли аргумент целым числом или атомом. Разные утверждения могут потребоваться и для конкретизированных и неконкретизированных аргументов. Приводимые ниже предикаты позволяют программисту включить в утверждения эти дополнительные условия.
Целевое утверждение var(X) согласуется с базой данных, если на текущий момент X является неконкретизированной переменной. Таким образом, возможен следующий диалог:
?- var(X).
да
?- var(23).
нет
?- X = Y, Y = 23, var(X).
нет
Неконкретизированная переменная может представлять часть некоторой структуры, которая еще не полностью заполнена. Примерами могут служить неотмеченные клетки на доске для игры в крестики-нолики, рассмотренной в разд. 4.3.3, и незаполненные части упорядоченного дерева, представляющего словарь в разд. 7.1. При работе с такими структурами предикат var очень, полезен при определении, являются ли некоторые части структуры уже заполненными или нет. Это может предотвратить «случайную» конкретизацию переменной при попытке анализа ее значения. Например, при работе со словарем, представленным в виде упорядоченного дерева, может потребоваться узнать, имеется ли уже вход для некоторого ключа, не создавая такой вход в случае его отсутствия. При игре в крестики-нолики может возникнуть необходимость определить, занята или нет некоторая клетка. Попытка сопоставить неконкретизированную переменную с «о» или «х» привела бы просто к тому, что соответствующий символ был бы помещен в клетку, соответствующую переменной.
Целевое утверждение nonvar(X) согласуется с базой данных, если X на текущий момент не является неконкретизированной переменной. Предикат nonvar является, таким образом, противоположным по отношению к предикату var. Действительно, он может быть определен на Прологе следующим образом:
nonvar(X):- var(X),!, fail.
nonvar(_).
Целевое утверждение atom(X) согласуется с базой данных, если текущее значение X является атомом в смысле языка Пролог. Как следствие возможен следующий диалог:
?- atom(23).
нет
?- atom(apples).
да
?- atom('/us/qris/pl. 123').
да
?- atom("этo строка").
нет
?- atom(X).
нет
?- atom(book(bronte,w_h,X)).
нет
Целевое утверждение integer(X) согласуется с базой данных, если на текущий момент X обозначает целое число. Этот предикат можно использовать при определении простого предиката для упрощения арифметических выражений, где необходимо знать, является ли выражение целым числом (см., например, разд. 7.12).
Целевое утверждение atomic(X) согласуется с базой данных, если на текущий момент X обозначает либо целое число, либо атом. Предикат atomic может быть определен через предикаты atom и integer следующим образом:
atomic(X):- atom(X).
atomic(X):- integer(X)
6.4. Работа с утверждениями как с термами
Пролог позволяет программисту анализировать и изменять свою программу (т. е. утверждения, которые используются для доказательства согласованности его целевых утверждений). Это непосредственно следует из того, что утверждения можно рассматривать как обычные структуры языка Пролог. В связи с этим в Прологе есть встроенные предикаты, позволяющие программисту следующее:
• Создавать структуру, представляющую утверждения в базе данных.
• Добавлять к базе данных утверждение, представленное заданной структурой.
• Удалять из базы данных утверждение, представленное заданной структурой.
Большинство операций над базой данных могут быть выполнены с помощью этих предикатов и обычных операций языка Пролог для конструирования и декомпозиции структур. В дополнение к приведенным здесь примерам в разд. 7.8 представлены некоторые способы использования данных предикатов для добавления и удаления утверждений.
Прежде чем мы рассмотрим соответствующие предикаты, необходимо понять, как утверждения Пролога могут быть представлены в виде структур. Для простого факта такой структурой является соответствующий ему предикат с аргументами. То есть факт, подобный
нравится(джон,Х)
может рассматриваться как обычная структура с функтором нравится (имеющим два аргумента) и аргументами джон и X. С другой стороны, правило можно рассматривать как структуру с главным функтором ':-'(с двумя аргументами). Этот функтор объявлен как инфиксный оператор. Первым аргументом является заголовок утверждения, а вторым – его тело. Так что