Скачиваний:
20
Добавлен:
01.05.2014
Размер:
287.74 Кб
Скачать

Компилятор

Для Пролога-86 нет компилятора.

Запомненные состояния

В Прологе-86 нет ничего похожего на двоичные запомненные состояния СиПролога. Встроенный предикат "save/1", аргументом которого является имя файла, переписывает в файл в форме, доступной для восприятия чело­веком, все фразы текущей программы. При этом, если во фразах есть пере­менные, то они будут представлены своими внутренними именами.

Интерфейс с иными языками программирования

Если в Вашем распоряжении имеется исходный текст УНСВ Пролога, то в него можно добавить в качестве дополнительных встроенных предика­тов функции, написанные на языке Си.

Разное

Имеется встроенный предикат "eof", который будет истинным, если встретится состояние "конец файла" для текущего входного потока.

Ниже приводится текст библиотеки, обеспечивающей совместимость Пролога-86 с DEC-10 Прологом, что позволит выполнять в Прологе-86 программы из данной книги.

% Библиотека совместимости для % Пролога-86. Добавьте ее в файл

% "prolog. lib" или "prolog_lib"

% вместо встроенного предиката "name"

% пользуйтесь нижеследующие предикатом:

decl0name (atom, ИСписок) :—

nonvar (ИСписок),

char_ _list (ИСписок, ССписок),

name (Атом, ССписок),!.

declOname (Атом, ИСписок) : -

atom (Атом),

name (atom, ССписок),

char__list (ИСписок, ССписок), !.

get0(l): - getc(C), ascii(C, I), !.

put(l) :- ascii(C, I), putc(C),!.

:- op(700,xfy,=<).

X=<Y:-X<=Y.

:- op(700,xfx,==).

X==Y:- not(X=Y).

Турбо Пролог Поставщик

Турбо Пролог поставляется фирмой Борленд Интернэшнл. Он работает под управлением операционной системы MS-DOS на ЭВМ IBM PC и совмес­тимых с ними компьютерах.

Турбо Пролог - это компилятор (не интерпретатор!). Он отличается высокой скоростью компиляции и выполнения. Среда разработки прог­рамм Турбо Пролога на первый взгляд кажется превосходной, но на са­мом деле это не совсем так. Программа, написанная на Турбо Прологе, сильно отличается от других Пролог-программ, так как она всегда должна начинаться с директив компилятора. Общий вид программы:

trace /* по желанию */

project "название проекта" / * по желанию */

include "другой_исходный_файл"/* по желанию */

domains /* по желанию; объявляет */

лицо = symbol /* новые типы областей значений */

смена = symbol

database /*пожеланию; */

работает (лицо, смена) /* объявляет преди- */

/* каты, которые можно */

/ * добавлять и удалять */

predicates /* обязательно, объявляет * /

знает (лицо, лицо) /* область */

/ * каждого аргумента) * /

goal /* по желанию */

знает (А, В).

clauses /* как правило, необходимо; */

/* здесь располагается сам * /

/* текст программы */

работает (билл, дневная).

работает (нэнси, дневная).

знает (X,Y) :-

работает(Х,S),

работает (Y,S),

X<>Y.

Если в программе есть директива "goal" (цель), то при выполнении программы система прогона вычислит эту цель один раз и закончит прог­рамму. Если в программе нет директивы "goal", то во время выполнения программы пользователь может вводить запросы. Смысл других директив излагается ниже.

Синтаксис и встроенные предикаты

Синтаксис Турбо Пролога в значительной мере аналогичен синтаксису DEC-10 Пролога. Многие программы данной книги без каких-либо переде­лок будут работать под Турбо Прологом.

В качестве синонима символического обозначения : - можно использо­вать слово "if (если), вместо ; можно использовать слово "or" (или), а вместо , — слово "and" (и). Комментарии в Турбо Прологе записывают­ся между символами / * и * /. Символ % не является признаком коммен­тария.

В Турбо Прологе имеются некоторые встроенные предикаты, анало­гичные предикатам DEC-10 Пролога.

Приведем встроенные предикаты Турбо Пролога, эквивалентные не­которым часто используемым встроенным предикатам DEC-10 Пролога:

DEC-10 Пролог

Турбо Пролог

Пояснения

is/2

=/2

арифметическое вычисление

var/1

free/1

успешен, если аргументом является неконкретизированная переменная

nonvar/1

bound/1

успешен, если аргументом не является неконкретизированная переменная

\==/2

< >/2

успешен, если аргументы не одинаковы

get0/1

readchar/l

считывает символы с текущего входного устройства

В Турбо Прологе отсутствует предикат, эквивалентный предикату " =/2" DEC-10 Пролога (этот предикат унифицирует два любых терма). В Турбо Прологе невозможно определить операции.

В Турбо Прологе имеются встроенные предикаты "asserta", "assertz" и "retract", предназначенные для модификации текущей программы. Од­нако, в отличие от других описанных здесь версий Пролога, аргументами этих трех предикатов должны быть только факты, а не правила. Любой предикат, фразы которого предполагается удалять и добавлять, должен быть объявлен как предикат базы данных при помощи директивы ком­пилятора "database". К примеру, предикат "работает/2" объявлен в при­веденном выше участке исходного файла как предикат базы данных.

У встроенного предиката "write" может быть любое число аргументов. Существует встроенный предикат "writef", первым аргументом которого должна быть строка форматов. После первого аргумента может распо­лагаться произвольное количество других аргументов. В Турбо Прологе отсутствует предикат, эквивалентный встроенному предикату "read/1" DEC-10 Пролога, но имеются предикат "readln/1", считывающий строку символов, и предикат "readtenn/2", который считывает терм. Первым ар­гументом встроенного предиката "readtenn/2" должна быть спецификация области значений, которая определяет то, какие типы термов может счи­тывать данный предикат (см. ниже подраздел о типах) .

Вместо встроенных предикатов "see", "tell" и т.д. в Турбо Прологе имеются следующие предикаты, предназначенные для управления фай­лами:

openread(N,F)

openwrite(N, F)

openappend(N, F)

openmodify(N, F)

Здесь F имя файла в операционной системе MS-DOS, N внутрен­нее имя, выбранное программистом, которое будет использоваться при обращении к открытому файлу. Встроенный предикат "openread" открыва­ет файл для чтения. Встроенный предикат "openwrite" открывает файл для записи. Встроенный предикат "openappend" открывает файл для добав­ления записей в конец файла. Встроенный предикат "openmodify" открыва­ет файл и для чтения, и для записи. В файл произвольного доступа можно внести изменения, если он открыт при помощи встроенного предиката "openmodify", а для позиционирования указателя записи используется встроенный предикат "filepos/3".

writedevice(N)

N — внутреннее имя файла, открытого при помощи встроенного пре­диката "openwrite", "openmodify" или "openappend". Этот предикат соотносит файл с текущим устройством вывода, так что выходная информа­ция, вырабатываемая при любых вызовах встроенного предиката "write" или "writef", пойдет в этот файл.

readdevice(N)

N — внутреннее имя файла, открытого при помощи встроенного преди­ката "openread". Этот предикат соотносит файл с текущим входным уст­ройством, так что информация, вводимая при любых обращениях к встро­енным предикатам "readchar/1", "readln/1", "readint/1", "readreal/1" или "readterm/2", будет поступать из этого файла.

closefile(N)

N —внутреннее имя открытого файла. Данный встроенный предикат закрывает этот файл.

Арифметические функции

Арифметические операторы ("=", "<" и т.д.) в дополнение к обыч­ным арифметическим операциям позволяют вычислять ряд функций, сре­ди которых в первую очередь нужно отметить следующие:

abs(X) % абсолютное значение Х

sqrt(X) % квадратный корень из X

ехр(Х) % число е в степени Х

log(X) % десятичный логарифм Х

1n(Х) % натуральный логарифм Х

sin(X)

cos(X)

tan(X)

arctan(X)

и т.д.

Типы

Турбо Пролог отличается от других версий Пролога тем, что в нем должен быть объявлен тип области значений (domain type) для всех аргументов каждого предиката. В Турбо Прологе изначально имеются нижеследующие простые типы области значений:

char

integer

real

string

symbol

file

К типу «char» относятся одиночные символы, к типу «symbol» — атомы.

Типы «string» и «symbol» взаимозаменяемы, хотя они и имеют различное внутреннее представление. Приведем простой пример, показывающий, как можно определить новые типы области значений через простые типы и как типы области значений употребляются в объявлениях предикатов:

domains

имя = symbol predicates

сделка (имя, real) clauses

сделка (боб, 37.50).

сделка (мери, 4.75).

сделка (сью_элен, 50.00).

Поскольку в объявлении области значений записано «имя = symbol», «имя» становится новым типом области значений, совпадающей с областью «sym­bol». Если при выполнении данной программы пользователь попытается воспользоваться запросом к предикату "сделка", задавая неверные типы области значений, то Турбо Пролог выдаст сообщение об ошибочном ис­пользовании типов области значений.

Структуры можно определять как новые типы -области значений, выражая их через простые типы области значений. Приведем версию прог­раммы "сделка" из разд. 2.2. Оба аргумента предиката "сделка" являются структурами.

domains

имя = symbol

сумма = integer

структура_клиент = клиент (имя, сумма, integer)

структура_дата = дата (integer, integer, integer) predicates

сделка (структура_клиент, структура_дата) clauses

сделка (клиент (смит, 29,4), дата (87,4,22) ).

сделка (клиент (ли, 35,7) , дата (86,10,30) ).

Если одним из аргументов предиката является список, то область зна­чений этого аргумента следует объявить как объект*, где «объект» — это область значений каждого элемента списка. Приведем в качестве примера версию процедуры "member", которая будет работать со списком, вклю­чающим целые числа:

domains

список—целых = integer*

predicates

member (integer, список_целых)

clauses

member (X, [X | _]).

member (X, [_ | Y] ) :- member (X, Y).

В данной программе проявляется недостаток принятой в Турбо Проло­ге строгой типизации: если пользователь напишет запрос к процедуре "member", аргументом в котором будет список, содержащий атомы, дей­ствительные числа или структуры, то Турбо Пролог выдаст сообщение об ошибочном использовании типа области значений и не будет выполнять программу. На практике это означает, что программист должен предусмот­реть заранее, элементы каких типов могут попадаться в списке, который будет аргументом процедуры "member", и включить их в объявление областей значений. Тем самым необходимость объявления областей зна­чений существенно уменьшает потенциальную возможность использова­ния составленной программы в каких-либо других целях. Помимо этого, становится невозможным написание предикатов метаязыка, см. ниже под­раздел "Разное".

Очевидно, что объявления типов областей значений сильно влияют на работу алгоритма унификации в Турбо Прологе. Вообще говоря унифика­ция терма, находящегося в запросе, с термом из фразы программы может произойти только в том случае, если во время компиляции программы эти термы были объявлены с совместимыми типами области значений.

Строки

Перечислим имеющиеся в Турбо Прологе встроенные предикаты, пред­назначенные для работы со строками.

readln (Строка)

Этот предикат считывает запись данных с текущего входного устрой­ства и возвращает ее в виде строки.

frontchar (Строка, ПервСимв, Остаток)

Этот предикат берет первый символ из начала строки и возвращает оставшуюся часть строки через «Остаток».

frontstr(N, Строка, Начало, Конец)

Здесь N - целое число, «Строка» - это строка по меньшей мере из N символов. Данный предикат возвращает первые N символов строки «Строка» через переменную «Начало» (которая также является строкой), а остальные символы строки «Строка» — через переменную «Конец».

fronttoken (Строка, Признак, Остаток)

Если переменная «Строка» конкретизирована, то данный предикат на­ходит первое слово или число, содержащееся в переменной «Строка», и возвращает его через переменную «Признак». Остаток строки возвраща­ется через переменную «Остаток».

str_len (Строка, Длина)

Данный предикат возвращает число символов, содержащихся в стро­ке «Строка».

Преобразование типов

В Турбо Прологе имеются нижеследующие встроенные предикаты, предназначенные для преобразования значений от одного типа к другому:

str_char (Строка, Символ)

str_int (Строка, Целое)

str_real (Строка, Действительное)

/ * преобразовать ascii-код в соот- */

/* ветствующий ему символ: */

char_int (Символ, Целое)

/* преобразовать строку, приведя ее */

/* целиком либо к буквам верх- */

/* него регистра (заглавные буквы), */

/* либо к буквам нижнего ре - */

/* гистра (строчные буквы) */

upper_lower (Верх_Строка, Ниж_Строка)

Соседние файлы в папке Гл.6,7,Прилож.,Допол