После загрузки системы Пролог пользователю становится доступен ряд системных предикатов. Они определяются с помощью либо самого Пролога, либо языка низшего уровня, используемого для реализации Пролога.
Описание предикатов и способы их применения содержатся в документации по конкретной реализации Пролога. При доказательстве некоторых предикатов имеет место так называемый побочный эффект. Благодаря ему обеспечивается интерфейс с пользователем и обработка файлов. Предикаты, обладающие побочным эффектом. обычно реализуются не на Прологе, а на языке низкого уровня, например Ассемблере, либо на языке высокого уровня, таком, как Паскаль.
Встроенные предикаты не могут быть изменены пользователем, а попытка заменить их, применяя предикаты assert и retract, приведет к сообщению об ошибке.
Программная среда Пролога состоит из двух частей:
программный модуль Пролога;
база данных Пролога.
Программный модуль включает интерпретатор Пролога (в некоторых реализациях и компилятор), драйвер ввода/вывода и, кроме того, системные процедуры. Пользователь обычно не имеет возможности изменять программный модуль.
База данных Пролога содержит набор основных, заранее определенных предикатов. Кроме того, резервируется пространство для добавления предикатов, которые будут объявлены пользователем. Механизмы добавления, удаления и обновления утверждений, заданных пользователем, классифицируются следующим образом:
1) добавление и удаление утверждений;
2) добавление утверждений из файла и замена имеющихся утверждений на утверждения, находящиеся в файлах для того же самого предиката (ввод программ и повторный ввод программ).
Файл Пролога состоит из утверждений. Утверждение есть факт или правило. Утверждения обрабатываются интерпретатором (компилятором) Пролога и потому должны удовлетворять синтаксическим определениям.
Добавление и удаление утверждений
Как уже говорилось, в Прологе имеется набор встроенных предикатов, позволяющих добавлять или удалять утверждения из базы данных. В гл.7 мы ввели предикаты asserta, assertz и retract, служащие для обновления базы данных. Подытожим ранее сказанное и рассмотрим встроенные предикаты retractall и abolish.
assertz(X)
X должен быть конкретизирован термом, не являющимся переменной. Терм интерпретируется как утверждение и добавляется в базу данных Пролога. Утверждение помещается в конец базы данных, или если существует процедура с теми же функтором и арностью, то добавляется к этой процедуре. (В некоторых реализациях Пролога допустимы исключения из приведенного правила, потому необходимо обратиться к руководству по конкретной системе.)
asserta(X)
Определяется аналогично предикату assertz(X), но новое утверждение становится первым утверждением в процедуре с теми же функтором и арностью.
retract (X)
X должен быть конкретизирован составным термом. В базе данных осуществляется поиск утверждения, голова и тело которого сопоставляются с термом X. Первое такое утверждение затем удаляется.
retractall(X)
Удаляет из базы данных все утверждения, функтор и арность которых сопоставимы с X.
abolish(P,A)
Удаляет из базы данных все утверждения для процедуры Р с арностью А.
Описанные предикаты служат для обновления базы данных Пролога во время выполнения программы.
Возможность динамического обновления программы довольно часто применяется в Прологе. После удаления части базы данных с помощью предикатов retract и abolish необходимо запустить механизм «сборки мусора» для восстановления памяти. Алгоритм, выбранный для чистки памяти, зависит от реализации Пролога.
Считывание утверждений в базу данных
Для того чтобы добавить новые утверждения в базу данных, пользователь вводит
:- consult(user).
Такая команда Пролог-системы вызывает считывание утверждений с терминала пользователя до тех пор, пока не встретится символ конец_файла. Типичная последовательность имеет вид:
?- consult(user). /* начало считывания
/* утверждений
: утверждение 1 /* Обратите внимание, что
/* использован другой знак
/* приглашения системы
: утверждение 2
:$ /* символ конец_файла
?- /* снова появилось обычное
/* приглашение системы
Утверждения 1 и 2 добавлены к базе данных и будут выбраны при попытке Пролога доказать цель с теми же функтором и арностью.
Более короткий вариант записи consult(user):
?- [user].
В данном случае используется тот же символ конца файла $.
Пользователю будет нелегко вводить одни и те же предикаты при каждом новом сеансе работы. Для устранения нежелательной ситуации в Прологе реализован механизм, позволяющий считывать группы предикатов или программы пользователя. Пусть мой-файл - файл пользователя. Утверждение
?- consult(мой-файл).
считывает содержимое файла мой-файл. Целевое утверждение consult(X) всегда выполняется успешно. В результате утверждения из файла мой-файл добавляются в базу данных Пролога. Если при чтении одного из утверждений обнаруживается синтаксическая ошибка, выдается сообщение об этом утверждении, но обработка оставшихся утверждений продолжается до тех пор, пока не будет найден конец файла. Целевое утверждение consuIt(X) нельзя передоказать. Если X не является именем реально существующего файла или файл не может быть открыт, то выдается сообщение об ошибке. При вводе программы из файла в ней иногда встречаются команды или директивы, относящиеся к системе Пролог. Они отличаются от утверждений, добавляемых в базу данных, тем, что им предшествует оператор?- или:-.
Целевое утверждение consult(F) добавляет утверждения из файла F в конец существующей базы данных. Пролог пытается сопоставить цель с добавленным утверждением только в том случае, если при прямом доказательстве попытка согласования существующего утверждения закончилась неудачей. Допускается замена новым утверждением утверждения, ранее записанного в базу данных, для чего используется встроенный предикат reconsult. Он работает аналогично предикату consult, но утверждения, считываемые в базу данных, замещают ранее записанные утверждения с теми же функтором и арностью.
В качестве аргументов предикатов consult и reconsult могут выступать списки файлов. Например:
consult([‘F1’,’F2’,...]).
reconsult([‘F1’,’F2’,...]).
Предикаты сохранения и восстановления
После добавления новых утверждений в базу данных пользователь имеет возможность сохранить копию текущего состояния системы и в следующем сеансе продолжить работу, начиная с записанного состояния. Для этого применяется предикат save. Утверждение
save('мой-файл').
сохраняет текущее состояние базы данных Пролога в файл, называемый мой-файл. Целевое утверждение save(X) нельзя передоказать. В случае, если не существует файла с именем X или если его невозможно открыть, то выдается сообщение об ошибке.
Успешно выполнив сохранение текущего состояния базы данных Пролога в файл, мы можем вернуться к прежнему состоянию, используя предикат restore:
геstоrе('мой-файл').
Чтение символов
Системные предикаты get(X), get0(X), skip(X) служат для ввода символов с терминала пользователя. Коды символов различаются в зависимости от используемой реализации Пролога. В микрокомпьютерах в основном применяется код ASCII*, а в больших ЭВМ (таких, как ICL2900) - код EBDIC**.
Перечисленные предикаты определяются следующим образом.
get0(X)
Предикат вызывает считывание одного символа с клавиатуры. Если переменная X неконкретизирована, то X принимает значение кода символа. Если же переменная X конкретизирована, то вводимый символ сопоставляется с X. Целевое утверждение будет успешно доказано только в том случае, если символ сопоставим с X.
get(X)
Предикат вызывает считывание одного или нескольких символов с клавиатуры до тех пор, пока не будет считан символ пробела. Если переменная X неконкретизирована, то код символа отождествляется с X и доказательство утверждения заканчивается успехом. Если же переменная X конкретизирована, целевое утверждение будет доказано только в случае, если вводимый символ сопоставим с X.
skip(X)
Предикат считывает символы с клавиатуры или из текущего входного файла, пока не встретится символ с кодом X, тогда доказательство цели заканчивается успешно. Переменная X может быть целочисленным выражением.
Запись символов
Для вывода символов используются системные предикаты: put(X), tab(X) nl. Они определяются следующим образом.
put(X)
Символ с кодом X записывается на терминал. Допускается, чтобы X был целочисленным выражением. Доказательство целевого утверждения put(X) всегда заканчивается успехом. X может быть кодом как управляющего, так и алфавитно-цифрового символа.
tab(X)
На терминал выводится X пробелов. X может быть целочисленным выражением.
nl
Происходит переход на новую строку терминала.
Рассмотрим примеры:
put(65) на терминал выводится символ А
(подразумевается ASCII код)
put(66+32) выходится символ b
put('C') выводится символ С
put([100]) выводится символ d
put(‘e’+’A’-‘a’) выводится символ Е
put(a(b)) выдается сообщение об ошибке
Считывание термов
Предикаты
read(X), readb(X) и read(X, Y)
служат для считывания термов. Приведем их определение.
read(X)
Если переменная неконкретизирована, то она означивается термом, считанным с терминала. Попытка пользователя напечатать выражение, не являющееся термом, приведет к ошибке. Вводимая информация должна заканчиваться точкой. В случае, если переменная X конкретизирована термом, попытка доказать целевое утверждение заканчивается успехом только при условии, что вводимый с терминала терм сопоставим с X. В противном случае попытка доказательства завершается неудачей.
readb(X)
Данный предикат аналогичен предикату read(X), но вводимый терм не должен заканчиваться точкой.
read(X,Y)
Доказательство предиката завершается успехом, если считываемый терм отождествляется с X, и неудачей в противном случае. При успешном доказательстве переменная Y становится списком, состоящим из имен переменных, входящих в терм X. Пролог переименовывает переменные, встретившиеся в вводимом терме. Таким образом, когда попытка доказать целевое утверждение read(X,Y) заканчивается успехом, список Y содержит внутренние имена переменных, входящих в терм X. Как и при использовании предиката read(X), после вводимого терма должна стоять точка.
readb(X,Y)
Предикат аналогичен предикату read(X,Y). Различие состоит в том, что пользователь не должен печатать точку после ввода терма.
Примеры:
После запроса:
?-read(X).
система ожидает ввода. Если пользователь напечатает:
test (5).
то в результате переменная X получит значение
Х - test (5)
Задав вопрос
?- read (джек (мужчина)).
и введя терм
test.
получим ответ:
нет.
При запросе:
?-read(X, Y).
вводим терм
fred(P, a(Q)).
в результате получаем
X = fred(_55,a(_57))
Y=[[P |_55],[Q | _57]]
где _55 - внутреннее имя переменной Р, а _57 - внутреннее имя переменной Q.
Запись термов
Рассмотрим предикаты, служащие для записи термов.
write(X)
Данный предикат выводит терм на экран. Если X содержит конкретизированные переменные, то на экране отображаются термы, которыми эти переменные конкретизированы. Если X содержит неконкретизированные переменные, они выводятся как уникальные целочисленные переменные. Сцепленные переменные, входящие в X, отображаются в виде одного и того же целого значения. Например, в ответ на запрос
?- write(cyммa(N, S,N+l)).
на экране появится
сумма (_35,_36 is_35+l ) .
writeq(X)
Предикат аналогичен предикату write(X) кроме случая, когда X содержит атом или функторы, которые в программе следует заключать в кавычки. Предикат writeq записывает такие величины на экране в кавычках. Например, в результате запроса
?- writeq('fred. txt').
на экране появится
'fred. txt'
display (X)
Предикат выводит терм X в стандартной скобочной префиксной
форме записи. Например, запрос
?- display (X+Y).
вызовет появление на экране записи:
+ (X, Y)
Описанные выше предикаты ввода/вывода осуществляют считывание и запись на терминал. Клавиатура связывается со стандартным входным потоком, а экран - со стандартным выходным потоком. Входной и выходной потоки могут осуществлять связь с различными файлами пользователя, требующимися во время сеанса работы с Пролог-системой. Для этого файл объявляется в качестве стандартного входного потока, и рассмотренные выше предикаты для ввода производят считывание из файла, а не с клавиатуры. Подобным образом файл назначается в качестве стандартного выходного потока. В таком случае приведенные предикаты для вывода осуществляют запись в файл, а не на экран.
Для переопределения стандартных потоков используются следующие предикаты.
see(F)
Определяет в качестве стандартного входного потока файл F.
seen(F)
Предикат переопределяет стандартный входной поток с файла F на клавиатуру. Прежде чем с помощью предиката see(F2) определить в качестве стандартного входного потока файл F2, следует с помощью предиката seen(F1) отменить связь файла F1 со стандартным входным потоком.
tell(F)
Целевое утверждение определяет стандартным выходным потоком файл F.
told(F)
Целевое утверждение переопределяет стандартный выходной поток с файла F на экран. Перед тем как с помощью предиката tell(F2) определить в качестве выходного потока новый файл F2, необходимо с помощью предиката told(F1) переключить текущий выходной поток с файла F1.
Помимо перечисленных в Прологе есть два предиката, позволяющие выяснить, с какими файлами связаны стандартные потоки.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 |


