Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по языку Пролог.doc
Скачиваний:
83
Добавлен:
28.06.2014
Размер:
507.39 Кб
Скачать

Методические указания

Язык программирования турбо пролог

ВВЕДЕНИЕ

Язык программирования Пролог был создан в конце 60-х годов в Марсельском университете под руководством А. Колмероэ в результате работы над проектом по созданию системы анализа и понимания естественного языка. В начале Пролог использовался в основном для доказательства теорем и был основан на методе резолюции А. Робинсона. Первый интерпретатор Пролога был написан П. Русселем в 1973 и оказал сильное влияние на своих преемников. Дальнейшее развитие языка (до 1980 г.) было связано с формированием его синтаксиса и семантики. В результате в качестве стандарта была принята версия, разработанная под руководством Д. Уоррена в Эдинбурге.

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

  1. ОПИСАНИЕ: ТУРБО ПРОЛОГ СИСТЕМ

1. 1. Структура меню Турбо Пролога

Система Турбо Пролога имеет главное меню, четыре рабочих окна и меню Помощи (рис. 1. 1). На рис. 1.2 а, б приведена полная структура главного меню системы

Files Edit Run Compile Options Setup

Editor Dialog

Message Trace

F2 – Save F3 –Load F9 – Compile Alt-X – Exit

Line1 Col 1 Work. Pro Insert

Load WORK.PRO

Рис 1.1. Среда Турбо Пролога

Рис 1.1. Среда Турбо Пролога

File Edit Run Compile

E – вызывает редактор и активизирует окноредактора

R – запуск на решение

Memory

OBJ file

EXE file (auto link)

Project (all modules)

Link only

Load

Pick

New File

Save

Write to

Directory

Change dir

OS shell

Quit

--Load file—

Имя файла 1

Имя файла 2

Имя файла3

Имя файла7

Рис 1.2 а. Структура меню Турбо Пролога

Options Setup

Link Options

Edit PRJ file

Compilerdirectives

Map file Off

Libraries

Memory allocation

Run-time check

Error level None (O)

Non-determ Warning Off

Variable used once Warning On

Print menu in EXE-file Off

Trace Off

Diagnistics Off

Colors

Windows size

Directories

Miscellanecus

Load SYS file

Save SYS file

Color & Window size

Edit window

Dialog window

Message window

Trace window

Aux edit window

Color only

Line (main) menu

Pop up menu

Help line

Break check On

Stack check On

Overflow check on integers On Щт Off

Code array 1000

Stack 600

Trail array 10

Heap size 0

Current directory

OBJ directory

EXE directory

Turbo directory

Rows Columns Requirers

25 80

25 90 MultyScan

25 120 EGA+

25 132 MultyScan

43 80 EGA

43 90 MultyScan

43 120 EGA+

43 132MultyScan

50 60 VGA

IBM-CGA Adapter Off

Auto load message Off

Screen mode 25*80

Keyboard configuration

Help lines

Main menu

Edit window

Xedit window

Display window

Resize window

View window

Printer log

Select line name

Brouse directory

Goal (run time)

Trace menu

Alter trace

Color Selection

Heap for arrors

Cursor movement

Insert & delete

Block functions

WordStar – like

Miscellaneous

Global functions

Hot keys

Рис. 1.2 б. Структура меню Турбо Пролога

и набор дополнительных меню.

Выбор альтернатив меню. Пользователь может выбрать одно из альтернатив меню следующим способом:

- по первой заглавной букве. Выбрать альтернативу непосредственно из меню и нажать первую букву из имени альтернативы. Например, FдляFileилиLдляLinkerOptionsи т. д.

- при помощи указателя активной альтернативы. Для этого необходимо при помощи ключей UpиDownпереместить указатель активной альтернативы на выбранное меню и нажать клавишуENTER.

- "горячие" ключи. Для выбора альтернатив из главного меню необходимо нажать клавишу Altодновременно с первой буквой из имени выбранной альтернативы. Например,Alt-0 позволяет вызвать альтернативуOptions,Alt-E- позволяет войти в окно редактора из произвольной точки системы. Указанные действия можно выполнить, находясь в любой точке Пролог системы.

Покинуть меню и вернуться в предыдущие состояние среды можно при помощи нажатия клавиши Esc. Если вы находитесь в окне редактора, то для того, чтобы вернуться в главное меню, необходимо нажатьCtrl-K-DилиF-10.

"Горячие" ключи. Выше говорилось о том, что Пролог система практикует назначать альтернативы меню на определенные сочетания клавиш клавиатуры, т. е. на "горячие" ключи. При этом нажатие любого из ключей приводит квыполнению той альтернативы меню, которая связана с этим ключом. Причем, в любой момент времени пользователь может получить список всех "горячих" ключей (нажатиемAlt-H), имеющих место в системе ( табл. 1. 1 ).

Турбо Пролог предоставляет пользователю самому переопределить все ключи, определенные в системе по умолчанию. Для этого необходимо загрузить OLD.SYS:SETprosys=c: \tprolog2\old.sys,

который содержит описание установок для системы. Указанная команда вставляется в AUTOEXEC. ВАТ файл. Если имеется необходимость переопределить существующие начальные установки системы, то это можно сделать при помощиSetup/Misсellaneous/Keyboardменю.

Таблица 1.1

Действие

"Горячий ключ"

Меню эквивалент

Выход из Пролог-системы

Alt-X

F/Quit

Работа с файлами

Alt-F

главное меню F

Временный выход в ДОС

Alt-D

F/OS Shell

Режим редактирования

AIL-E

главное меню Б

Режим изменения среды

Alt-0

главное меню 0

Режим компиляции

Alt-C

главное меню С

Режим изменения начальных

установок Пролога

Alt-S

главное меню 5

Показать "горячие" ключи

Alt-H

S/M/K/Hot Keys

Показать номер версии

Alt-F10

Загрузить файл

F3

F/Load

Выбрать файл

Alt-F3

F/Pick

Сохранить файл

F2

F/Save

Запустить программу на

решение

Alt-R

главное меню R

Компиляция в памяти

F9

С/Меmoгу

Компиляция в OBJ

Shirt-F9

C/OBJ File

Компиляция в БХЕ

Ctrl-FQ

C/EXE File

Компиляция проекта

Alt-F9

C/Ptoject


1.2. Окна системы Турбо Пролога

Окно редактора. Редактировать существующий файл или создать новый в Турбо Пролог системе можно только в окне редактора ( т. е. в редакторе). Имеется два способа войти в редактор:

- войти в редактор из главного меню;

- войти в редактор при помощи "горячего" ключа Alt-E. причем в этом случае в редактор можно попасть из любой точки Пролог системы.

В результате будет активизировано окно редактора, т. е. окно редактора будет заключено в двойную рамку. Если в момент входа в редактор в Пролог систему не был загружен файл, то окно редактора будет пустым, а новому файлу по умолчанию будет присвоено имя WORK.PRO.

Окно редактора состоит из двух частей:

- основной области окна, где можно видеть и редактировать текст рабочего файла;

- информационной части окна, где приводится информация о редактируемом тексте и о местоположении курсора.

В нижней части экрана расположена строка Помощи, где перечислены основные ключи и соответствующие им команды.

В любой момент можно выйти из редактора в главное меню, предварительно нажав клавишу F10 илиEsc.

Окно трассировки. Окно трассировки позволяет следить за ходом выполнения программы. Для этого необходимо компилировать программу с опцией traceв режимеOn. Установить режим трассировки можно в менюOptions/ComnpilerDirectives, а также непосредственно в исходном тексте программы. Результаты трассировки можно получать непосредственно в окно трассировки, выдавать на устройство печати или запомнить в файл (клавишаAlt-P)PROLOG.LOG. Отметим, что в данном случае активным является окно трассировки.

Окно сообщений. Турбо Пролог система о всех своих действиях сообщает пользователю через окно сообщений. Например, на рис. 1.3 в окне сообщений показано, что начальная загрузка системы выполнена без указания имени конкретного файла пользователя, поэтому в систему был загружен пустой файл с именем WORK.PRO. В дальнейшем пользователем был загружен файл с именемFIRST.PRO. Система сообщила обо всех этих действиях. Если пользователь даст

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

Files Edit Run Compile Options Setup

Editor Dialog

Message Trace

F1 – Help F2 – Save F3 –Load F5 – Zoom F6 – Next F7 – Xcopy F8 – Xedit F9 – Compile F10 - Menu

Line1 Col 1 Work. Pro Insert

goal

makewidow(1,7,7,”My first Program,

write ((“Please type your \n n

cursor(5,4),

readln(Name), nl,

write(“welcom to\n Turbo Prolog

Load WORK.PRO

Load C:\First.PRO

Рис 1.3. Окно редактора Турбо Пролога

Окно диалога. Окно диалога является специальным средством, при помощи которого Пролог система активно взаимодействует с пользователем. Получить доступ к окну диалога, находясь в среде системы, можно при помощи ключа Alt-R.

Если пользователь имеет исходный текст Пролог-программы в окне редактора, который не содержит блока цели (GOAL), то Пролог система после компиляции исходного текста сама активизирует окно диалога и потребует от пользователя сформулировать цель. Если пользователь не содержит текста в окне редактора, то Пролог система активизирует окно диалога без компиляции. После этого вы можете вводить запросы на языке Турбо Пролога.

Результат работы можно послать на печать или в файл с именем PROLOG.LOGпри помощи ключаAlt-P.

1.3. Команды Турбо Пролог системы

Турбо Пролог система позволяет выполнить:

- манипулирование файлами;

- редактирование файла;

- выполнение программы;

- компиляцию программы;

- изменение конфигурации среды для Пролог системы;

- изменение конфигурации Пролог системы.

1 3 1. Манипулирование файлами

Создать новый файл. Создать новый файл можно следующими

способами

- нажать на клавишу Е при первом вхождении в Пролог систему;

- в главном меню выбрать Files/Newи нажатьEnter; в главном меню выбратьFiles/Loadи нажатьEnter. После этого откроется дополнительное окно, где необходимо указать имя создаваемого файла. Расширение .PROможно опускать, т. к. система автоматически сделает .PRO. В первых двух случаях создастся новый файл с именемWRK.PRO.

Загрузить существующий файл. Загрузить существующий файл можно следующими способами:

- в главном меня выбрать Files/Load;

- нажать ключ F3.

После этого откроется окно, где необходимо указать имя загружаемого файла с указанием каталога и полного пути.

Если не указать имени загружаемого файла и нажать на клавишу Enter, то тогда система откроет дополнительное окно, в котором будут показаны все файлы с расширением .PROиз активного каталога. После этого при помощи стрелок управления курсором необходимо подвести указатель к требуемому файлу и нажать на клавишуEnter.

Если вместо имени файла указать имя каталога и затем нажать на клавишу Enter, то в дополнительном окне будут показаны все файлы с расширением .PROиз указанного каталога.

Если вместо имени файла задать *. * и нажать на клавишу Enter, то в дополнительном окне будут показаны все файлы из активного каталога.

- в главном окне выбрать Files/Pick. После этого откроетсяPickокно, где будут показаны все файлы, которые ранее загружал пользователь, После этого при помощи стрелок управления курсором необходимо подвести указатель к требуемому файлу и нажать на клавишуEnter.

Сохранить текст программы в файле. Сохранить текст программы в файле всегда можно при помощи клавиши F2. Если вы находитесь в главном меню, то можно воспользоваться средствами менюFiles/Save.

Записать текст программы на диск. Для того чтобы записать текст программы в файл на диске, необходимо в главном меню выбрать Files/WriteТо. В результате будет открыто окно, где необходимо указать имя файла, куда будет помещен текст программы. В результате в активном каталоге будет создан новый файл с указанным именем.

Если в активном каталоге существует файл с указанным именем, то Пролог система потребует подтверждения для записи в указанный файл. При положительном ответе старое содержимое файла будет уничтожено, а на его место будет записан указанный текст программы. При указании имени файла можно указывать каталог и путь к нему.

Если вместо имени файла нажать на клавишу Enter, то Пролог система откроет новое окно, в котором покажет все файлы с расширением .PROиз активного каталога. В этом окне необходимо выбрать файл, куда следует поместить текст исходной программы и нажать на клавишуEnter.

Указание активного каталога. Для указания активного каталога пользователю предоставляются следующие возможности:

- в главном меню выбрать Files/Directory. В результате Пролог система откроет дополнительное окно, где необходимо указать все необходимые каталоги и пути к ним.

- в главном меню выбрать Files/ChangeDir. В результате Пролог система откроет дополнительное окно, где необходимо указать имя требуемого каталога.

- в главном меню выбрать Setup/Directories. В результате Пролог система откроет окно, где необходимо указать все активные каталоги, а также каталоги, содержащие .OBJ, .ЕХЕ файлы и саму Пролог систему. Эти спецификации обычно задаются при инсталляции Пролог системы на ЭВМ и сохраняются в файле конфигурацииPROLOG.SYS.

Временный выход в операционную систему. Осуществить временный выход в операционную систему можно следующим образом:

- в главном меню выбрать Files/OSShell;

- нажать на ключ Alt-D.

В результате вы временно покинете Турбо Пролог систему и сможете выполнить любые командыMS-DOSили выполнить запуск других программ. Единственным ограничением на выполняемые программы является ограничение по памяти, т. к. временно прекращая свои действия - Пролог система остается в оперативной памяти ЭВМ. Для того, чтобы осуществить возврат в Пролог систему, необходимо на клавиатуре дисплея набрать командуEXITи нажать на клавишуEnter.

Выход из Пролог системы. Выход из Пролог системы можно осуществить, если в главном меню выбрать Files/Quitили нажать ключAlt-X.

1.3.2. Редактирование файла.

Редактор Турбо Пролога используют систему команд, аналогичную редакторам WordStarиSideKick(Ta6л 1.2).

1.3.3. Выполнение программы

При помощи команды RUNосуществляется запуск программы, находящейся в оперативной памяти, на выполнение. Если данная программа уже была откомпилирована и текст программы, расположенный в окне редактора, не был изменен, то Пролог система приступит к выполнению программы.

Если текст программы был изменен, то Пролог система выполнит компиляцию текста, а затем приступит к выполнению программы.

Программы в Турбо Пролог системе могут быть выполнены двумя способами;

- если Пролог-программа содержит блок цели, то Пролог система выполнит эту цель. В процессе выполнения программы Пролог система может открыть окно Диалога, если это специфицировано программой. После выполнения Пролог программы необходимо нажать клавиву SpaceBarи вернуться в главное меню.

- если Пролог-программа не содержит блок цели, то Пролог система активизирует окно Диалога и потребует от вас сформулировать цель (задать блок цели - Goal).

В процессе выполнения программы пользователь может выполнять команды, перечисленные в таблице 1.3.

1.3.4. Компиляция программы.

При компиляции текста программы, находящейся в окне Редактора, пользователь может указать Пролог системе режимы компиляции:

  • в оперативной памяти. В результате Пролог система выполнит компиляцию активного файла и оставит объектный код в оперативной памяти. Это код может быть выполнен при помощи команды RUN; - получить .OBJфайл. Эту возможность обычно используют при

Таблица1.2

Команды редактора "Горячие" ключи

Управление курсором:

Перевести курсор на одну строку вверх 

или

Ctrl-E

Перевести курсор в начало окна Ctrl-Home

Перевести курсор в начало файла Ctrl-PgUp

или

Ctrl-QR

Перевести курсор на одну строку вниз 

или

Ctrl-X

Перевести курсор в конец окна Ctrl-End

Перевести курсор в конец файла Ctrl-PgDp

или

Ctrl-QС

Перевести курсор на один символ вправо 

или

Ctrl-D

Перевести курсор на один слово вправо Ctrl

или

Ctrl-F

Перевести курсор в конец строки End

или

Ctrl-QD

Перевести курсор на один символ влево 

или

Ctrl-S

Перевести курсор на один слово влево Ctrl

иди

Ctrl-A

Перевести курсор в начало строки Home

или

Ctrl-Q5

Ввод и удаление:

Добавить новую строку

Ctrl-N

Добавить выделенный блок Ctrl-F5

или

Ctrl-KС

Удалить символ под курсором Del

или

Ctrl-G

Удалить символ слева от курсора Backspace

или

Ctrl-H

Уделить слово справа от курсора

Ctrl-T

Удалить строку под курсором Ctrl-Backspace

или

Ctrl-Y

Удалить часть строки слева от курсора

Ctrl-Q T

Удалить часть строки справа от курсора

Ctrl-Q Y

Манипулирование блоками:

Отметить начало блока

Ctrl-К В

Отметить конец блока

Ctrl-KК

Скопировать (ввод) отмеченный блок Ctrl-F5

или

Ctrl-KС

Переместить отмеченный блок

Ctrl-K V

Удалить отмеченный блок

Ctrl-K Y

Восстановить удаленный блок Ctrl-F7

или

Ctrl-KU

Сохранить отмеченный блок в файле

Ctrl-K W

Выдать на печать отмеченный блок

Ctrl-K P

Поиск/Поиск и замена:

Поиск Ctrl-F3

или

Ctrl-QF

Продолжить поиск Shift-F3

или

Ctrl-O

Заменить F4

или

Ctrl-Q L

Продолжить замену Shift-F4

или

Ctrl-L

Таблица 1.3

Ключи

Действия

F2

Сохранить текст программы, расположенной

в окне Редактора

F3

Загрузить новый файл

F6

Показать другие окна Пролог системы

F8

Переписать предыдущую цель на следующую

строку Диалогового окна

Shift-F10

Изменить размеры и переместить окно Диалога

Ctrl-S

Временно сохранить результата работы Программы в окне При нажатии любой клавиши будет

продолжен вывод в окно

Ctrl-Break

Прекратить выполнение программы и вернуться

в главное меню

Alt-P

Активизировать Printer-Logменю. В этом меню

пользователь должен указать куда направить

результаты трассировки, диалога и выполнения

программы

Alt-T

Активизировать окно трассировки

работе с проектом (project). После компиляции активного файла, т. е. получения для него .OBJфайла, пользователя может загрузить другой файл, выполнить необходимую его редакцию, откомпилировать его, а затем приступить к сборке (link) всего проекта;

- получить . ЕХЕ файл. Эта возможность позволяет пользователя автоматически откомпилировать активный файл или группу файлов, указанных в проекте, и выполнить сборку выполняемого модуля:

- выполнить проект. Эта возможность позволяет выполнить указанный вами проект;

- выполнить сборку программы. Эта возможность позволяет получить .ЕХЕ файл из уже существующих . OBJфайлов проекта.

1.3.5. Изменение конфигурации среды для Пролог системы

Возможности задания конфигурации среды для Пролог системы показаны на рисунке 1.4.

Задание конфигурации для среды Пролог системы заключается:

- задание опций для сборки программ. Здесь необходимо установить режим ОН для спецификации MapFileс целью получения описания перекрестных ссылок.

- указать необходимые библиотеки;

- создать новый или отредактировать . PRJфайл;

- задать опции для компиляции. Здесь пользователь может запросить:

- объем требуемой памяти. Память измеряется в параграфах (1 параграф = 16 байт и 4096 параграфов =64 Кбайт.);

  • объем кодового массива. Задание для кодового массива размера более 4000 параграфов соответствует определению модулей с FARуказателями:

  • объем стека.

1. 3. 6. Изменение конфигурации Пролог системы

При инсталляции Пролог системы вам предлагается некоторая конфигурация системы, которую вы можете изменить по своему желанию.

Files Edit Run Compile Options Setup

Project name

Map file off

Libraries

Link Options

Edit PRJ file

Compiler directives

Libraries:

Memory allocation

Run-time check

Error level None (O)

Non-determ Warning Off

Variable used once Warning On

Print menu in EXE-file Off

Trace Off

Diagnistics Off Off

None (0)

Default (1)

Maximum (2)

Trace

Short Trace

Off

Break check On

Stack check On

Overflow check on integers Off

Code array (paragraphs) 1000

Stack (paragraphs) 600

Trail array (paragraphs) 10

Heap size (paragraphs) 0

Рис. 1.4. Меню задания конфигурации среды Пролог системы

Пролог система предоставляет в распоряжение пользователя средства для изменения конфигурации самой Пролог системы. По желании вы можете задать (рис. 1.26) цвет для каждого из окон системы, размер и местоположение каждого из окон, указать необходимые рабочие каталоги и т. п. Все дополнительные сведения по изменению конфигурации системы вы может найти в TurboProlog2.0ReferenceGuide[4].

2. ОПИСАНИЕ ТУРБО ПРОЛОГА

2.1. Имена

В языке Пролог имена используются для обозначения констант, доменов, предикатов и переменных. Имя состоит из букв, цифр или знака подчеркивания.

Например, можно использовать длинные имена, содержащие прописные, заглавные буквы, знак подчеркивания или только знак подчеркивания:

MyLongestVariableNanieSoFar,

pair_who_might_make_a_happy_couple(henry_viii, ann_boleyn). pair_who_might_make_a_happy_couple( _ , ann_boleyn).

Ограничения. Язык Пролог резервирует некоторый список имен для своих внутренних целей, которые пользователю запрещено использовать в качестве имен:

and domains goal include

clauses elsedef if or

constants enddef ifdef predicates

databaseglobalifndef

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

assert chain_terms format retractall

asserta consult free save

assertz db_dtrees not term_replace

bound db_chains readterm trap

chain_inserta fail reaf_term write

chain_insertafter findall retract writef

chain_insertz

2.2. Константы

Константы в Турбо Прологе могут быть одного из шести типов:

1. char- символ, заключенный в одиночные апострофы (например, ‘f’);

2. integer- любое целое число из диапазона -32768 до 327676;

3. real- любое вещественное число из диапазона +/-1е-307 до +/-1е+308.

Примеры вещественных чисел:

42705

-9999

86.72

-9111.929437

-521e238

64e-94

-79.8Эе+21

Примечание. При необходимости целые числа автоматически могут

переводится в вещественные числа.

4. stringпоследовательность символов, заключенных в двойные

апострофы, например, "your never say boodbye". Указанная последовательность не должна превышать 64 Кбайт.

5 symbol- имеется два формата для представления символьных

констант.

1) последовательность букв, цифр и знаков подчеркивания, начинающаяся с прописной буквы ( только ASCIIсимволы );

2) последовательность символов, заключенных в двойные апострофы ("). ('Этот случай обычно используется для представления объектов, начинающий с заглавной буквы или содержащие пробелы.)

Примеры:

telephon_nyinber

"railway_ticket"

"Dorid_inc"

"animal lower"

6. File-см. главу 4.

2.3. Выражения, переменные, структуры, списки и составные

выражения

Выражения. Выражение в Турбо Прологе может быть одиночным символом (char), целым числом (integer), вещественным числом (real), строкой символов (string), символьным объектом (symbol) (в случае атомарного значения), переменной, структурой, списком или составным выражением.

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

- имена символьных констант должны начинаться со строчной буквы;

- имена переменных должны начинаться с пропиской буквы или знака подчеркивания;

Одиночный знак подчеркивания используется в качестве имени для анонимной переменной. Значение анонимной переменной не доступно для пользователя.

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

Структуры. Язык Пролог ориентирован на представление фактов или высказываний.Каждый факт выражает некоторое отношение между одним или более объектами. Для представления отношений в Турбо Прологе используются структуры, имеющие следующий формат:

имя_отношения (имя_объекта1, имя_объекта2, ... , имя_объектаN) ,

где имя_отношения есть произвольная последовательность символов, цифр или знаков подчеркивания ("_"), а имя_объекта есть произвольная последовательность символов, цифр или знаков подчеркивания, начинающаяся с прописной буквы. Например, имеются следующие факты:

Александр любит ловить рыбу,

Катя любит читать,

Елена любит плавать.

Эти факты можно представить:

Likes( "Александр", "Ловить_рыбу").

llkes( "Катя" ."Читать").

likes( "Елена", "Плавать").

Однако хорошо известно, что не все высказывания могут быть представлены при помощи указанных выше структур. Например, при помощи этих структур не удается записать следующий факт:

Катя любит все то, что любит Елена.

Запись в подобного типа высказываний в Прологе имеет вид (в виде правила):

likes( "Катя" . Х ) :-likes( "Елена" , Х ). ,

где Х есть переменная, а символ ":-" обозначает логическую связку "ЕСЛИ". Общая форма для представления подобного типа фактов имеет вид: ВЫРАЖЕНИЕ:-

ВЫРАЖЕНИЕ_1,

ВЫРАЖЕНИЕ_2,

ВЫРАЖЕНИЕ. N.

Эту запись можно прочитать: Некоторое ВЫРАЖЕНИЕ имеет место, ЕСЛИ имеют место все перечисленные справа от знака ":-" выражения, т.е. ВЫРАЖЕНИЕ_1, ВЫРАЖЕНИЕ_2, . . , ВЫРАЖЕНИЕ_N. Знак "," соответствует логической связи "И". Выражения справа от знака ":-" могут иметь сложную логическую структуру, причем, для указания порядки выполнения логических операций используются скобки "(" и ")". Выражения и подвыражения - могут соединяться при помощи связки "ИЛИ" (";"), если это необходимо. Отметим, что каждое подобное выражение, представляющее факт, должно всегда заканчиваться точкой (".").

Списки. Список, наряду со структурой, является основной структурой данных в Прологе. Элементы списка отделяются друг от друга запятой и заключаются в квадратные скобки ( [ ] ). Примеры:

[1 . 2 , 3 ]

[ dog , cat , canary]

["valerie ann" , "jonatan" , "michael" ).

Для того чтобы определить список из целых чисел, необходимо записать:

domains

integerlist = integer*

Знак звездочка ( * ) указывает на то, что определяется список, который может содержать произвольное количество элементов (монет быть пустым). Необходимо отметить, что все объекты должны принадлежать одному и тому же домену и быть объявлены следующим образом:

domains

objectlist = objects*

objects = ….

Манипулирование списками осуществляется при помощи специальной операции, обозначаемой вертикальной чертой - " | ", которая позволяет выделить "голову" (т.е. первый элемент списка) и "хвост" (часть списка без первого элемента) списка. (Эта операция аналогична операциям CARиCDRв языке программирования ЛИСП.) Примеры на обработку списков приведены в таблице 2.1.

Спиcок с "головой" Х и "хвостом"Yможно записать:

[ X | Y].

Примеры:

1. Пусть имеется цель:

soores( [ X; Y] ).

и факт в базе знаний:

scores([l,2,4,6,7,9,1,0]). ,

то переменная Х будет связана с "головой" списка ( Х = [ 1 ] ), aпеременнаяYс "хвостом" списка (Y =[2,4,6,7,9,1,0] ). В таблице 2.2 приведены дополнительные примеры на связывание свободных переменных при сопоcтавлении списков

2. Поиск элемента в списке. Предположим, имеется список имен:

[ john , leonard , eric , frank ]

и необходимо проверить, существует ли имя erikв указанном списке. Для этого необходимо ввести отношение 'member' между двумя объектами - именем ('name') и списком имен ('namelist):

member( name, namelist ).

Таблица 2.1

Список

"Голова" списка

"Хвост" списка

[ 'a', 'b', 'с']

'a'

[ 'b' , 'о' ]

[ 1 ]

1

U(пустой список)

[ ]

неопределена

неопределена

[[1,2,3],[2,3 ,4],[ ]]

[1, 2, 3]

[[2,3,4],[]]

Таблица 2.2

Список 1

Список 2

Значения переменных

[ X, Y, Z]

[one, two, three]

X=one, Y=two, Z=three

[ 7 ]

[ X, Y ]

X=7, Y=[]

[1,2,3,4]

[ X , Y | Z ]

X=l, Y=2, Z=[3,4]

[ 1 , 2 ]

[ 3 | X]

Связывание переменной X

не произошло, т. к. не

совпали "головы" списков

Возможны два случая:

- если "голова" списка совпадает со значением переменной Name, то можно положительно ответить на запрос, причем, элементы "хвоста" нас уже не интересуют На языке Пролог это можно записать.

member( Name, [ Name | _ ]).

- если "голова" списка не совпадает со значением переменной Name, то необходимо выполнить поиск имени в "хвосте" списка. Для этого необходимо выполнить предикатmemberдля "хвоста" списка т. е.

member( Name, [ _ | Tail ] :- member( Name , Tail ).

Если теперь выполнить цель:

member( erik , [ John , leonard , eric , frank ]). ,

то в качестве ответа получим значение "Истинно",

Составные выражения. Пролог предоставляет возможность строить объекты из других объектов, т.е. допускает составные объекты. Рассмотрим, например, следующее высказывание:

owns(александр,book("Ситуационное управление","Поспелов Д. А.")). ,

которое говорит, что Александр имеет книгу с названием "Ситуационное управление", написанную Д.А. Поспеловым. Аналогично можно записать:

owns(Александр,dog( сеттер, “Бетти”)). ,

которое означает, что Александр имеет сеттера по кличке Бетти. Оба эти высказывания были построены с использованием структур bookиdog, которые позволили нам выразить различные семантические отношения между объектами в рамках одной структурыowns.

Общий формат для представления составных объектов:

функтор(объект_1, объект_2,.. ,объект_N).

Функтор без объектов имеет вид:

функтор( )

или

функтор.

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

domains

объект_j- подобъект_1;подобъект_2:...;подобъект_N.

где ";" есть разделитель для альтернативных подобъектов.

В нашей случае имеем:

domains

my_object - book(tittle, author); dog(dog_type, name)

name, title, author = symbol

predicates

own( name, my_object)

book(title,autl1or)

dog(dog_type, name)

Пример (Программа управления курсором на экране дисплея.) Для управления курсором введем предикат:

Move_cursor( row, column, movement),

который осуществляет движение курсора на экране дисплея. Программа может иметь вид:

domains

row, column, step = integer

movement = up( step) ,down( step);

lef t( step); right( step)

predicates

move_cursor ( row, column, movement)

clauses

move_cursor(R C,up( Step)) :-

Rl = R - Step, cursor-(R1,C).

move_cursor(R,C,down( Step)):-

R1 = R + Step,cursor (R1,C).

move_cursor(R,C,left(_)): -

Cl = C - cursor(R,C1)

move_cursor(R,C,up(_)) :-

Cl = R+ l,cursor(R,C1).

Пусть необходимо выполнить цель:

move_cursor (4,9,up(2)),

которая позволяет переместить курсор на две строки вверх. Следуют отметить, что при написании программы мы воспользовались встроенным предикатом cursor, который специфицирует позицию курсора на экране

2.4. Программные секции

Программа на языке Турбо Пролог обычно состоит из нескольких программных секций( табл. 2. 3).

Перечисленные секции не являются обязательным атрибутом Пролог-программы. Например, если не указать в программе секцию goal, Пролог

Программные секции

Содержание

1.

Опции компилятора

Опции компилятора, указываемые в начале программы

2

constants

Область задания констант

3.

domains

Область определения доменов

4.

database

Область определения базы данных

5.

predicates

Область определения предикатов

6.

goal

Область задания цели

7.

clauses

Область задания определений предикатов

система потребует от пользователя задания цели в момент выполнения программы. Для того чтобы получить выполняемую программу, необходимо, чтобы эта программа содержала цель. Если программа не содержит цель, то ее выполнение возможно только в среде Турбо Пролога. Программа может состоять на одной секции цели:

goal

readint(X), Y=X+3, write("X + 3 = ", X).

Обычно программа содержит секции predicatesиclauses. Секцияdomainsпозволяет пользователю определить списки, составные объекты и внутренние переменные.

Для того чтобы программа содержала несколько секций для domains,predicates,databaseилиclauses, должны быть выполнены следующие требования:

константы, домены и предикаты должны быть определены до их использования в программе. Причем, при определении домена можно ссылаться на домены определенные позже;

- только одна цель должна быть в программе;

- все определения одного и того же предиката должны стоять в определенной последовательности (одно за другим);

- все глобальные определения должны предшествовать локальным:

- любой секции databaseможно присвоить уникальное имя.

2.4.1. Секция констант

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

constants

и имеет следующий синтаксис:

<Id> = < Macro definition>

Каждое макроопределение представляет собой последовательность символов, причем для определения каждой константы используется только одна строка. Например:

constants

blue = 1

green = 2

red = 4

bgi_path = "c:\\tprolog\\dbi"

grayfill50 = [#ss, #55, $aa, #55, #aa, #55]

language = english

project_module = true

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

menu_colors(red,green,blue),

find_bgi(bgi_path),

My_fill_pattern(grayfill,50),

text_convert(tprolog, language),

status( project_module),

Турбо Пролог вместо определенных выше констант подставить их конкретные значения;

menu_colors( 1, 2, 4),

find_bgi( "c:\tprolog\\dbi" ),

my_fill_pattern( [ #ss, $55, $aa, #55, #aa, #55 ] , 50),

text_convert( tprolog, english) ,

status(true),

2. 4. 2. Секция доменов

Секция доменов содержит все объявления доменов. Для этого используются следующие четыре формата:

name=d/* стандартный домен */

mylist=elementDom* /* списковый домен */

myCompDom = fi(d11,dl2.. ...d1n); /* домен составного */

f2(d21,d22,...'.d2n); /* объекта */

File - namel;name2;...;name /* файловый домен */

Стандартный домен. Эта запись определяет домен с именем name, который содержит элементы типаd, гдеd= {integer,char,real,ref,string,symbol}.

Данные объявления позволяют описывать синтаксически подобные, но семантически различные объекты. Например, можно объявить два различных домена типа integer:

apples, height « integer Списковый домен. Это описание является стандартным для определения списковых доменов. Здесьmylistпредставляет собой домен, содержащий списки элементов, тип которых определяетсяelementDom. В свою очередьelementDomможет быть или определяемым доменом или стандартным доменом.

Домены составного объекта. Это описание используется для задания домена, содержащего другие объекты. Здесь необходимо перечислить функторы и домены для всех его подобъектов. Например, мы можем объявить домен ownersи его подобъекты для факта:

owns(aлександр,book( "Ситуационное управление", "Поспелов Д.А."))

owners = owns( symbol, book) book = book( symbol, symbol) ,

где ownsесть функтор составного объекта,asymbolиbookявляются доменами подобъектов.

Файловый домен. Файловый домен используется тогда, когда необходима ссылка на файл при помощи символьного имени. Любая программа может содержать только один домен данного типа. Имена файлов могут быть заданы альтернативным способом:

file=books;dogs

В данном примере определяются два файла с именами booksиdogs.

2. 4. 3. Секция предикатов

Секция предикатов в Турбо Прологе выделяется специальным ключевым словом predicatesи содержит описание для всех предикатов, используемые в программе. Например:

predicates

predi1ane(domain_l,domain_2,... ,domain_N).

В этом примере prednameпредставляет имя предиката,adomain_1,domain_2,…,domain_Nесть стандартные домены или домены, определенные пользователем.

Турбо Пролог допускает несколько описаний для одного и того же предиката. Например, вы можете объявить, что предикат memberработает не только с именами, но и с числами:

predicates

member( name, namelist)

member( number, numberlist)

В этом примере аргументы name,namelist,number,numberlistявляются доменами, определенными пользователем. Заметим, что любое альтернативное описание предиката должно содержать такоеже число аргументов, что и основное описание.

2.4. 4. Секция баз данных

Секция баз данных определяет предикаты подобно секции предикатов. Однако предикаты, определенные в этой секции, содержат только факты без переменных. Этот факт, например при помощи операций assert,asserta,assertzилиconsult, может быть добавлен в базу данных во время работы программы.

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

2. 4. 5. Секция цели

Секция цели содержит описание цели. Наличие цели является обязательным условием для получения самостоятельно (вне среды Турбо Пролога) выполняемой программы. Если программа не содержит секции цели, то она может быть выполнена только в среде Турбо Пролога. В этом случае Пролог система откроет окно диалога и потребуют от пользователя цель. Следует отметить, что секция цели может содержать только одну цель. В Прологе имеется два типа целей:

- проверка истинности факта,

- поиск значений.

Например, если необходимо выяснить - "Любит ли Александр ловить рыбу ?",то нужно выполнить цель:

Goal: –

likes("Александр", "Ловить_рыбу").

В результате поиска система установит истинность этого факта и выдаст ответ:

true

Если факт отсутствуют в базе знаний, то Пролог считает его ложным, т. е. в Прологе радируется следующий принцип; "Истинно только то, что явно присутствует в базе знаний". Если, в случае второго типа целей необходимо выяснить - "Что любит Александр ?",то нужно выполнить цель

Goal:-

likes("Александр",X).

В результате поиска система сопоставит все имеющиеся у нее факты с данным образцом, свяжет переменную Х с каждым из найденных значений и выдаст ответ:

Х =Ловить_рыбу

1 Solution,

т. е. выдаст все найденные решения и число решений. Если решения не будет найдено, то система выдаст:

Nosolution

2.4.6. Секция определений для предикатов (clauses)

Эта секция содержит либо факты, либо правила, имеющие заголовок правила, отделенный от "тела" правила знаком ":-" и "тело" правила, содержащее список предикатов. Каждый факт или правило связано с определенными в секции predicatesпредикатами и всегда заканчиваются точкой ( "."). Например, факт:

likes( "Александр", "Ловить_рыбу").

состоит из имени предиката likesи списка аргументов ("Александр", "Ловить_рыбу"), заключенных в скобки "( )".

2.5. Процесс выполнения цели в Турбо Прологе

2.5.1. Процесс сопоставления цели с образцом

Пусть имеется программа:

domains

title,author = symbol

pages = integer

publication = book(title,pages)

predicates

written_by(author,publication)

long_monograph(publication)

clauses

written_by("Мартин Дж.",

book("Развитие автоматизированных систем". 328)).

written_by("Тиори T.",

book("Проектирование структур баз данных", 607)).

long_monograph(Title): - . .

witten_by(_,book((Title,Length)),Length > 400.

Выполним цель:

written_by(X,Y)

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

written_by( X , У )

| |

written_by("Мартин Дж.",book("Развит, автоматиэ. систем", 328))

, что при сопоставлении цели с первым из фактов переменная X примет значение "Мартин Дж.", а переменная У значение book( "Развитие авто­матизированных систем", 328). Аналогичным образом будут просмотрены все остальные факты и в результате система выдаст ответ:

X = "Мартин Дж.", Y = book("Развит, автоматизир. систем", 328)).

X = "Тиори Т." , Y = book("Проектир. структур баз данных", 607)).

2 solutions

Выполним цель:

written_by( X ,book("Проектирование структур баз данных", Y )).

Турбо Пролог система выполнит сопоставление данной цели с первым из фактов.

В результате чего, X примет значение "Мартин Дж." и будет выполнено

written_by( X ,book("Проектир. структур баз данных", Y ))

| |

written_by("Мартин Дж.",book ("Развитие автоматиа. систем" , 328 ))

сопоставление следующих образцов:

book("Проектир. структур баз данных", Y )

| |

book("Развитие автоматиз. систем" , 328)

Здесь сопоставления не произойдет, т. к. первые аргументы предикатов являются различными объектами. Следовательно, сопоставление данного факта с целью окончилось неудачей, и связь между переменной X и объектом "Мартин Дж" будет устранена Турбо Пролог система перейдет к сопоставлению с целью следующего факта, в результате чего будет получен ответ:

X = "Тиори Т." , Y - 607

1 solutions

Аналогичным образом моют быть выполнена следующая цель:

long_monograph( X).

Процесс поиска решения удобно представлять в виде дерева (рис. 2.1).

long_monograph( X )

---------------------------------

long_monograph( Title )

/ \

written_by(_,book((Title,Length)) Length > 400.

----------------------------------------------------------------------

written_by("M ".book(“Paзв. автомат. систем”, 328))

Рис. 2.1.

При выполнении последней цели Турбо Пролог система сопоставит цель с заголовком правила. Дм выполнения этого правила необходимо выполнить две подцели:

written_by(_,book((Title,Length))2 0 и Length > 400 ,

которые в дереве вывода представляются левой и правой ветвями со­ответственно. Турбо Пролог система будет выполнять сначала первую из подцелей, т. е. поиск решения в дереве вывода пойдет по левой ветви, а затем будет выполнять следующую подцель, т. е. пойдет по правой ветви. В нашем случае при выполнении первой подцели будет выполнено ее сопоставление с первым фактом. Переменные X и Title примут значение "Развитие автоматизированных систем", а переменная Length примет значение равное 328. После успешного выполнения первой из подцелей будет выполняться вторая подцель:

328 > 400

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

X = "Проектирование структур бае данных"

1 solutions

2.5.2 Управление процессом поиска решения

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

Предикат fail позволяет инициировать бэктрекинг, т.е. эффект от fail аналогичен эффекту, который вызовет невыполнимое отношение типа:

2 = 3 .

Рассмотрим действие этого предиката на примере. Пусть имеются следующие факты:

father ( александр, екатерина).

father ( cергей, никита).

father ( иван, виктор).

father ( виктор, александр).

где предикат father ( X , Y) означает, что X является отцом Y. И имеется запрос:

Goal:-

father( X, Y).

В результате выполнения этого запроса Турбо Пролог система выдаст ответ:

X = александр, Y = екатерина

X = сергей, Y = никита

X = иван, Y = виктор

X = виктор, Y = александр

4 solutions

Если теперь перефразировать эту цель следующим образом:

everybody: -

father(X,Y),write(X," - отец".Y,"\n"),fail.

и выполнить цель:

goal: -

everybody.

то получим:

александр - отец екатерина

сергей - отец никита

иван - отец виктор

виктор - отец александр

No solutions

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

Отсечение ("!"). Данный встроенный предикат позволяет ограни­чить действие бэктрекинга, т.е. бэктрекинг не распространяется на предикаты предшествующие "!". Это приводит к тому, что некоторое найденное решение не будет пересматриваться. Если теперь вернуться к предыдущему примеру и изменить определение для everybody следующим образом:

everybody: -

father(X,Y),write(X," - отец",У,"\n"),! .

При повторном выполнении цели:

goal: -

everybody.

Получим:

александр - отец екатерина

1 solutions

Другими словами, после того как найдено одно решение, процесс поиска будет закончен.

2.6. Условная компиляция

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

constants

egagraphic = 1

/* Необходимо помнить, что директивы

ifdef, elsedef и enddef

должен начинаться с 1 позиции */

ifdef egagraphic

goal

graphics(5, 1,1).

write("\nEGA Graphics"),

readchar( _ ).

elsedef

graphics(1,1,1),

write( "\nEGA Graphics"),

readchar( _).

enddef

Формат для записи выражений условной компиляции:

[ ifdef | ifndef ) <constant ID>

. . .

elsedef

. . .

enddef ,

где <constant ID> есть константа определенная в секции констант.

2.7. Включение дополнительных файлов в программу

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

include "DosFileName"

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

2.8. Директивы компилятора

Как уже говорилось выше (см. раздел 1.), Турбо Пролог имеет ряд . опций, которые позволяют управлять режимом компиляции. Например:

bgidriver config nobreak shorttrace

bgifont diagnostics nowarnings trace

check_determ errorlevel printermenu trail

code heap project

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

BGIDRIVER. Эта опция задается, если в выполняемой программе необходимо использовать специальный графический драйвер. Например:

bgidriver "_CGA_driver_far"

BGIFONT. Эта опция задается, если в выполняемой программе необ­ходимо использовать специальный графический шрифт. Например:

bgifont "_gothic_font_far"

CODE. Данная опция позволяет задать размер внутреннего кодового массива. По умолчанию его объем равен 16 Кбайт. Для больших программ необходимо указывать больший размер массива. Опция имеет формат:

code = Number_of_paragraphs ,

где Number_of_paragraphs указывает объем памяти в параграфах, требуемой под кодовый массив. Например, директива:

code = 1024

установит размер кодового массива равным 16 Кбайт. Отметим, данная опция влияет на размер

*. ЕХЕ файла.

CONFIG. Данная опция позволяет задать в программе конфигурацию среды Турбо Пролог системы, которая будет учтена непосредственно на этапе компиляции. Эта возможность может быть использована при форми­ровании среды отладки, используемой пользователем. Формат опции:

config "<MyConfigFileName>.sys"

HEAP. Эта опция позволяет указать объем памяти, необходимый для выполнения из DOS вашего *. ЕХЕ файла. Если вы не используете этой опции или укажите значение равно 0, то это равносильно использова­нию все свободной памяти. Формат опции:

heap = Number_of_paragraphs

PRINTERMENU. Использование этой опции позволяет пользователю распечатать результат выполнения *. ЕХЕ файла при нажатии Alt-P.

Описание и использование оставшихся из перечисленных выше опций компилятора подробно рассмотрено в разделе 6.

2.9. Модульное программирование

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

2.9.1. Проект и глобальные определения

Турбо Пролог использует два понятия при управлении модульным программированием: проект(project) и глобальные определения.

Проект. Если программа, написанная на Прологе, содержит несколько модулей, то Турбо Пролог система требует определение проекта, содержащего имена этих модулей. Перечислим этапы создания проекта:

1. Выбрать Edit_PRJ_File из Options menu.

2. Ввести имя нового файла в окно ввода и нажать на клавишу Enter.

3. Турбо Пролог откроет окно редактора и поместит туда вновь созданный файл с указанным вами именем и расширением . PRJ.

4. Содержимым этого файла является определение проекта. Формат проекта:

name_of_first_module+

name_of_second_module+

. . .

name_of_last_module

Каждый модуль специфицируется своим именем (без расширения).

5. После того, как вы отредактировали проект, необходимо налить на клавиш F2 и F10. Это действия позволят вам сохранить созданный файл, который будет помещен в активный каталог и вернуться в главное меню.

Глобальные определения. По умолчанию все имена, используемые в модуле, являются локальными. Турбо Пролог программы допускают взаи­модействие пересекающихся модулей только при помощи • глобальных определений, сделанных в секциях global predicates и global database. Домены, используемые в этих глобально определенных секциях, должны быть определены как global domains или быть стан­дартными доменами. Все модули проекта должны иметь одни и те же глобальные определения. Это можно добиться, например, если поместить вес» глобальные определения в один файл, который затем может быть включен и любой из модулей при помощи директивы include. Следует помнить, что все глобальные определения должны предшествовать локальным определениям.

При задании глобальных определений необходимо соблюдать пра­вила:

- для того чтобы секция была определена как глобальная, необходимо использовать специальный описатель global;

- при определении глобальных предикатов необходимо указание текущих образцов для вызова этих предикатов. Каждый глобальный предикат должен быть определен по схеме:

mypred(d_l, d_2, .... d_N) - (f, f, ..., f)(f, f, ... f)... ,

где d_l,. d_2, ... , d_N есть глобальные домены, (f. f, ..., f) есть текущий образец, а каждый из f есть указатель входа i (Input) или выхода о (Output). Например, в определении глобального предиката:

first_pred( name, home, age) - (i, i, i)(o,o,o)

name и home являются доменами типа string, a age типа integer. Аргу­менты first_pred могут быть все связаны (i, i, i) или все свободны (о, о, о).

Примечание: После редактирования любой из глобально определен­ной секции необходима перекомпиляция все модулей проекта.

2.9.2. Компиляция и сборка (link) модулей

Перед компиляцией и сборкой проекта необходимо выполнить сог­лашения:

1. Каждый модуль должен начинаться с указания опции компиля­тора project и включения всех глобальных определений. Например:

project "MYPROJ"

include "GLOBALS. PRO"

2. Один модуль должен содержать секцию цели. Этот модуль обычно называют главным модулем.

Для каждого модуля проекта может быть отдельно получен его *. OBJфайл. Затем, если выбрать в менюCompile/EXEFile, то проект автоматически будет собран в один *. ЕХЕ файл. Если вы выберетеCompile/Project, то предварительно будут перетранслированы все модули в проекте, а потом будет получен *.EXE. файл.

2.9.3. Пример

Этот пример иллюстрирует шаги разработки и выполнения программы из двух модулей. Предположим, что мы хотим иметь два программных модуля с именами MAIN. PRO и SUB1.PRO, файл-проект с именем MYPROJ. PRJ и файл с необходимыми глобальными определениями - GLOBDEF. PRO.

Шаг 1. Создадим файл-проект MYPROJ при помощи выбора в меню Option/Edit PRJ File и отредактируем содержимое файла, например:

main+sub1+

Нажмем клавишу F2 чтобы сохранить файл.

Шаг 2. Создадим, отредактируем и сохраним в файле с именем GLOBDEF. PRO следующие глобальные описания:

/* GLOBDEF. PRO */

global domains

name = string

global predicates

welcome(name) - ( i )

Шаг З. Создадим, отредактируем и сохраним в файле с именем MAIN. PRO следующий текст программы:

/* MAIN. PRO */

project "MYPROJ"

include "globdef. pro"

predicates

test ;

goal

test.

clauses

test:-

clearwindow,

write("Please write your name"),

nl.nl.nl,

readln(ThisName),

welcome(ThisName).

Шаг 4. Создадим, отредактируем и сохраним в файле с именем SUB1. PRO следующий текст программы:

/* SLB1.PRO */

project "MYPROJ"

include "globdef. pro"

clauses

welcome(Name): -

write("Welcome ".Name),

write(" Nice to meet you."),

sound(100,200).

Шаг 5. Вернемся в главное меню и выберем Project в основном ме­ню. Укажем имя проекта и нажмем на клавишу Enter. Турбо Пролог сис­тема автоматически будет транслировать каждый из модулей после чего соберет файлы INIT.OBJ, SUB1.0BJ, MAIN.OBJ, MYPROJ. SYM и

PROLOG. LIB в один выполняемый файл MYPROJ. EXE.

3. АРИФМЕТИЧЕСКИЕ ВЫЧИСЛЕНИЯ И ОПЕРАЦИИ СРАВНЕНИЯ

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

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

3.1. Арифметические выражения

Арифметические выражения состоят из операндов (чисел и пере­менных), операторов (+, -, *, /, div и mod) и скобок. Идентифика­торы в правой части от знака равенства (который является предикатом = ) составляют арифметическое выражение.

A = 1 + 6 / ( 11 + 3 ) * Z

Шестнадцатеричные числа могут быть представлены числом с предшествующим знаком доллара. Например:

$FFF = 4095

86 = S4A + 12

Значение выражения может быть вычислено, только если все переменные в момент вычисления определены. При этом вычисления производятся в установленном порядке, определяемом приоритетом операции. Операции с высшим приоритетом выполняются первыми.

3.2. Операции

Турбо Пролог может выполнять все четыре основные операции (сложение, вычитание, умножение и деление) между целыми и вещест­венными числами, Тип результата определяется в соответствии с таблицей 3.1

Таблица 3.1

Операнд 1

Оператор

Операнд Z

Результат

целое

+,-,*

целое

целое

вещественное

+,-.*

целое

вещественное

целое

+,-.*

вещественное

вещественное

вещественное

+,-.*

вещественное

вещественное

целое или

целое или

вещественное

/

вещественное

вещественное

целое

div

целое

целое

целое

mod

целое

целое

Таблица 3.2

Операция

Приоритет

+ -

* / mod div

- + (unary)

1

2

3

3.3. Порядок вычислений

Арифметические операции вычисляется в следующем порядке:

1. Если выражение содержит подвыражение с скобках, подвыра­жение вычисляется первым.

2. Если выражение содержит операцию умножения (*) или деления (/ , div или mod), эти операции выполняются слева направо.

3. Наконец, выполняются сложение и вычитание, также слева направо.

В выпажении A = 1 + 6 / ( 11 + 3 ) * Z подразумевается, что Z имеет значение 4, путем вычисления определим значение переменной А.

1. (11 + 3 ) - первое вычисляемое подвыражение, так как оно в заключено в скобки. Оно равно 14.

2. Затем вычисляется 6/14, так как / и * вычисляются слева направо. В результате получим 0.428571.

3. Далее 0.428571*4 дает 1.714286

4. Наконец, вычисляя 1+1.714285, получаем значение выраже­ния 2. 714285.

Если А принадлежит вещественному домену (real), то оно может получить значение 2.714285. Однако, если А принадлежит домену це­лого типа (integer), оно получит значение 3 (заметим, что резуль­тат округляется до ближайшего целого).

3.4. Функции и предикаты

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

Таблица 3. 3

-------------------------------------------------------------------------------------------------------------------------------

Функциональный предикат Описание

-------------------------------------------------------------------------------------------------------------------------------

X mod Y Возвращает остаток от деления (модуль) X деленного на Y

X div Y Возвращает частное X деленного на Y

abs(X) Если значение X -, положительная величина

val, аbs(X) возвращает это значение;

в противном случае возвращает -l*val

соs (X) Тригонометрические функции, требующие

sin (X) чтобы X был величиной, представленной в

tan (X) радианах

arctanf (X) Возвращает значение вещественного X

ехр (Х) Возводите в степень X

1n (Х) Логарифм из X по основанию е

log (X) Логарифм из X по основанию 10

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

random ( X) Ставит в соответствие X случайное

вещественное число; 0 <= Y < 1

random(X.Y) Ставит в соответствие Y случайное

целое число; 0 <= Y < X

round (Х) Округляет значение X

trunc(X) Усекает X (отбрасывает младшие разряды)

-------------------------------------------------------------------------------------------------------------------------------

3.5. Целочисленная и вещественная арифметика

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

3.6. Сравнение

Турбо Пролог может сравнивать арифметические выражения также как и символы, строки и идентификаторы. Следующее выражение в Турбо Прологе эквивалентно выражению: "Сумма X и 4 меньше 9 минус Y"

Х+4 < 9-Y

Оператор отношения "меньше чем" (<) показывает отношение между двумя выражениями, Х+4 и 9-Y. Турбо Пролог использует ин­фиксную нотацию которая означает, что оператор располагается меж­ду операндами (Х+4) вместо того чтобы предшествовать им (+(Х,4)). Полный ряд отношений, разрешенных в Турбо Прологе показан в табли­це 3. 4.

Таблица 3. 4

Идентификатор

Отношения

<

меньше

< =

меньше или равно

=

равно

>

больше

>=

больше или равно

<> или ><

не равно

3. 7. Равенство и предикат равенства

В Турбо Прологе такие операторы, как N = N1-2 показывают от­ношение между тремя объектами (N,N1 и 2) или отношение между дву­мя объектами (N и величиной N1-2). Если N еще свободно, оператор может быть удовлетворен присвоением N значения выражения N1-2. Это приблизительно соответствует тому, что в других языках прог­раммирования называется оператором присваивания. Заметим, что поскольку N1 является частью вычисляемого выражения, оно всегда должно быть определено (то есть должно быть связано со значением).

Когда вы для сравнения вещественных величин используете пре­дикат равенства (=) , нужно позаботиться о том, чтобы приближенное представление вещественных чисел не привело к непредсказуемым ре­зультатам. Например, цель:

7/3*3=7

потерпит неудачу. Это показывает, что сравнивая две вещественные величины на равенство, необходимо проверять, чтобы они не имели разное представление.

Пример:

Программа показывает как обработать приблизительное равенство. Она представляет собой интерактивную процедуру вычисления квадратного корня, для определения решений квадратного уравнения:

А*Х*Х + В*Х + С = 0

Наличие решений зависит значения дискриминанта D, определяе­мого как:

D = В*В - 4*А*С

- D>0 означает, что существует два различных решения.

- D=0 означает, что существует единственное решение.

- D<0 означает, что решений нет, если Х - вещественное ( могут быть одно или два комплексных решения ).

predicates

solve (real, real, real)

reply (real, real, real)

mysqrt (real ,real, real)

equal (real, real)

clauses

solve (A.B.C) :-

D=B*B-4*A*C

reply(_,_,D) :-

D<0, write ("No solution"). !.

reply(A,B,C), :-

D=0, X=-B/( 2*A) , write ( "x=”,X), !.

reply(A,B,D) :-

mysqrt(D.D.SqrtD).

Xl= (-B + sqrt D)/(2*A)

X2=(-B - sqrt D)/(2*A)

write ("xl=".Xl,"and x2=”,X2).

mysqrt(X, Guess, Root) :-

NewGuess=Guess-( Guess*Guess-X)/(2/Guess)

not( equal ( NewGuess, Guess) ) , ! ,

mysqrt (X, NewGuess, Root).

mysqrt ( _, Guess , Guess) .

equal(X.Y) :-

X/Y>0.99999, x/y<l.00001.

Чтобы решить квадратное уравнение эта программа вычисляет квадратный корень из дискриминанта D. Программа вычисляет квад­ратные корни по итеративной формуле, где новое значение (NewGuess) квадратного корня от X может быть получено из предыду­щего значения (Guess):

NewGuess=Guess- ( Guess*Guess- X) /( 2/Guess) .

Каждая итерация немного приближается к квадратному корню от X. Когда условие equal (X,Y) удовлетворяется, дальнейшего прибли­жения достичь нельзя и вычисление заканчивается. Программа может вычислить X1 и X2.

Xl= (-B + sqrt D)/(2*A)

X2=(-B - sqrt D)/(2*A)

3.8. Сравнение символов, строк и идентификаторов

Кроме числовых выражений вы можете также сравнивать простые символы, строки и литералы. Рассмотрим следующие сравнения:

‘a’<’b’ /* Символы */

"antony" > "antonia" /* Строки */

P1 = peter, P2 = sally, Pl>P2 /* Литералы */

Символы. Используя соответствующее значение кода ASCII для каждого символа, Турбо Пролог преобразует 'а' < 'Ь' в эквивалент­ное арифметическое выражение 97 < 98. Когда две строки или литерала сравниваются, результат зависит от сравнения символов на соответствующих позициях. Результат будет такой же, как при сравнении начальных символов, исключая случай, когда они одинаковы. В этом случае Турбо Пролог сравнивает следующую пару соответствую­щих символов и возвращает результат, если эти символы не равны, в противном случае сравнивается третья пара и так далее.

Строки. Сравнение "antony" > "antonia" оценится как "true" (истинное), так как первая пара различных символов содержит в первой строке букву у (значение 79 в коде ASCII), а в другой строке букву i ( ASCII значение. 69). Отметим, что сравнение “ аа “ > “ а “ истинно.

Аналогично, выражение "peter" > "sally" будет ложно, так как определяется сравнением значений ASCII первых букв слов "peter" и "sally". Символ 'р' располагается перед символом ‘s’ в алфави­те, поэтому 'р' имеет меньшее значение кода ASCII. Таким образом, выражение оценится как ложное.

Идентификаторы. Идентификаторы не могут непосредственно сравниваться из-за их синтаксиса. В случае P1 = peter, P2... например, идентификатор peter не может непосредственно сравни­ваться с идентификатором sally. Они должны быть связаны с пере­менными, которые сравниваются, или записаны как строки.

4. ВВОД - ВЫВОД В ТУРБО ПРОЛОГЕ

В этой главе мы рассмотрим встроенные предикаты для ввода и вывода. Далее будет показано, как в Турбо Прологе работает файловая система. Мы также рассмотрим домен file и несколько предопределенных файлов.

4.1. Вывод

До сих пор все результаты работы направлялись на экран, а ввод осуществлялся только с клавиатуры. Теперь мы рассмотрим стандартные предикаты ввода-вывода и познакомим вас с парой предикатов, которые позволят выполнять чтение из файлов.

В Турбо Пролог включены три стандартных предиката для вывода. Это предикаты write, nl и writef.

Предикат write может быть вызван с произвольным числом аргументов:

write( Paraml, Param2, ... ParamN) /* (i, i, ... i) */

Эти аргументы могут быть либо константами из стандартных до­менов, либо переменными. Если это переменные, то они должны быть входными параметрами.

Стандартный предикат nl (от new line - новая строка) всегда используется вместе с write. Он обеспечивает переход на новую строку на экране дисплея. Например, следующие подцели:

pupil (PUPIL,CL).

write (PUPlL, "is in the", CL, "class"),

nl,

write("-----------------------------------“).

могут привести к выводу на экран такого результата:

Helen Smich is in the fourth class

а следующая цель:

write("List1 = ",L1,". List2 = ",L2).

может дать:

List1 = [cow, pig, rooster], List2 = [1,2,3]

Так же, если My_sentence связана с

sentence (subject(john), sentenceVerb(sleeps))

то в следующей программе:

domains

sentence = sentence (subject ,sentence_verb)

subject = subject (symbol);.....

sentence_verb = sentence_verb( verb);…...

verb = symbol

clauses

. . . .

write(“SENTENCE=", My_sentence).

Вы сможете увидеть на дисплее:

SENTENCE = sentence(subject( john), sentenceVerb( sleeps))

Часто предикат write не дает вам много из того, чего бы вам хотелось иметь при печати таких сложных, объектов, как списки, но нетрудно написать программы, которые позволяли бы работать с та­кими объектами.

Предикат writef позволяет выполнить форматированный вывод; он использует следующий формат:

writef(FormatString,Argl,Arg2,... .ArgN) /* (i, i, ... i) */

Аргументы Arg1,...,Argn должны быть константами или связан­ными переменными, принадлежащими стандартным доменам. Сложные до­мены форматировать нельзя. Строка форматирования содержит обычные символы и форматные спецификаторы; обычные символы печатаются без модификации, а форматные спецификаторы имеют следующую форму:

%-m. pf

Символы спецификаторов формата, следующие за знаком процен­та, являются необязательными и имеют следующее значение:

дефис (-) показывает, что поле выравнивается слева (по умолчанию выравнивается справа).

m поле десятичное число, определяющее минимальную длину поля.

p поле десятичное число описывающее либо точность представ­ления с плавающей точкой, либо максимальное число симво­лов, печатаемых в строке.

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

Турбо Пролог распознает следующие спецификаторы формата поля f:

-------------------------------------------------------------------------------------------------------------------------------

f вещественные в представлении с фиксированной точкой ( 123.4)

е вещественные в экспоненциальном представлении ( 1.234е2 )

g вещественные, в формате f или е ( этот формат по умолчанию )

d символьные или целые как десятичные числа

u символьные или целые как беззнаковые целые

х символьные или целые как шестнадцатеричные числа

с символьные или целые как символы

R как число ссылки на базу данных (только для домена ref )

X как длинное шестнадцатеричное число

s как строки ( simbols и string )

-------------------------------------------------------------------------------------------------------------------------------

Примеры. Эти примеры показывают как можно использовать пре­дикат write для того, чтобы получить возможность с помощью ваших предикатов выводить на печать такие объекты как списки и сложные структуры данных.

1. Программа печатает список без открывающей и закрывающей квадратной скобки ( [ ] ).

domains

integerlist = integer *

namilist = symbol*

predicates .

writelist(integerlist)

writelist(namilist)

clauses .

writelist( [ ] ).

Writelist([H| T]) : -write(H,” ”), writelist( T ).

2. В следующем примере программа выводит элементы списка не более чем по пять элементов на строке.

domains

integerlist = integer *

predicates

writelist(integerlist)

write5((integerlist, (integer)

clauses .

writelist(NL) : -nl,write5(TL,0).

write5([ H| T] ,N) : -! ,write(H,""),

N1=N+1,write5(T,N1)

write5([], _).

3. Часто имеется необходимость иметь предикат, который выво­дит сложные структуры данных в более удобном для чтения виде. Программа выводит объекты типа:

plus(mult(x, number(99)), mult( number(3), x))

в виде

x * 99 + 3 * x.

(Это называется инфиксной записью.)

domains

expr = number( integer) ;x;log(expr);

plus( expr, expr) ;mult(expr, expr)

predicates

writeExp(x) :-write(x).

clauses

writeExp(x) :-write(‘x’).

writeExp(number (No)) : -write(No).

writeExp(log(Expr)) :- write("log(") ,

writeExp(Expr) ,

write(‘)’).

writeExp(plus(Ul,U2)): - writeExp(Ul), write(‘+’), writeExp (U2).

writeExp(mult(Ul,U2)): - writeExp(Ul), write(‘*’) ,writeExp (U2).

4. Следующая программа иллюстрирует действие различных форматных спецификаторов при форматном выводе с помощью writef.

А = one,

В = 330.12,

С = 4. 3333375,

D = "one two three",

writef ("A = ’%-7’ \nB = ‘%8.1e ‘\n",А,В),

writef ("A = ’%’ \nB = ‘%8.4e ‘\n", А, В),nl,

writef ("C= ’%-7.7g’ \nD = ‘%7.7‘\n",C,D),

writef. ("C = ’%-7.0f’ \nD = ‘%0‘\n",C,D),

writef ("char: %c, decimal: %d, hex: %x, unsigned: %u",97, 'a',33,-1).

После.запуска эта программа создаст следующий вывод:

А = ' one '

В = ' 3.3Е+02'

А = ' one '

В = '3.3012Е+02'

D = 'One two'

С = '4 '

D = 'one two three'

char: a, decimal: 97, hex: '21, unsigned: 65535

4.2. Ввод

Турбо Пролог включает в себя несколько стандартных предика­тов для чтения. Из них пять основных: readln (для чтения строк символов целиком); readint, readreal и readchar (для чтения це­лых, вещественных и символьных значений соответственно); и readterm (для чтения составных объектов). Все эти предикаты могут быть переопределены для чтения из файлов.

Имеются некоторые другие, более специализированные предика­ты, относящиеся к категории чтения: file4_sr (для чтения всего текстового файла в строку), inkey ( для чтения символа с клавиа­туры, если он нажат), keypressed ( для определения была ли нажата клавиша на клавиатуре) и unreadchar ( для возвращения символов в буфер клавиатуры). Эти специализированные предикаты не дают не изменяют своего действия при переопределении ввода.

Предикат readln читает текстовую строку и использует следую­щий формат:

readln( Line) /* ( о ) */

Домен для переменной Line должен быть либо строкового, либо символьного типа. Перед тем, как вы вызовете readln, переменная Line должна быть свободна. readln считывает до 127 символов (плюс возврат каретки) с клавиатуры, до 64K с других устройств. Если во время ввода с клавиатуры нажата клавиша Esc , геаdln потерпит не­удачу.

Предикат readint считывает целое значение, используя формат:

readint( X) /* ( о ) */

Домен для переменной X должен быть целого типа, а X перед вызовом должна быть свободна, readint будет считывать целое значение с текущего входного устройства (возможно с клавиатуры), пока не будет нажата клавиша Enter. Если считанная строка не соответствует синтаксису целых, readint терпит неудачу, и Турбо Пролог вызывает механизм поиска с возвратом. Если во время ввода с клавиатуры нажата клавиша Esc , readint терпит неудачу.

Предикат readreal работает в соответствии со своим названием: он считывает вещественные (real) числа ( аналогично readint, считы­вающему целые). Предикат readreal использует следующий формат:

readreal(X) /* ( о ) */

Домен для переменной X должен быть вещественного типа, а X должна перед вызовом быть свободна. Предикат readreal будет читать вещественные значения с текущего устройства ввода, пока не будет нажата клавиша Enter. Если ввод не соответствует обычному синтаксису

вещественных чисел, readreal терпит неудачу. Если во время ввода нажата клавиш Esc, readreal также терпит неудачу.

Предикат readchar считывает один символ с текущего устройства ввода, используя формат:

readchar (CharParam) /* ( о ) */

Перед вызовом readchar CharParam должна быть свободной пере­менной и должна принадлежать домену char. Если текущим устройством • ввода является клавиатура, readchar ждет, пока будет нажат один символ, после чего возвращает его. Если во время ввода нажата клави­ша Esc, readchar терпит неудачу.

Предикат readterm считывает сложные термы и превращает их в объекты. Он имеет следующий формат:

readterm(DomainName, Term) /* ( i, i ) */

.

Вы вызываете readterm с двумя аргументами: именем домена и термом, readterm читает строку и превращает ее в объект д&нного домена. Если строка не будет иметь вид объекта, сформированного предикатом write, readterm даст ошибку.

Предикат readterm может использоваться для обработки термов в текстовых файлах. Например, вы можете создать собственные вер­сии save и consult.

Предикат file_str читает символы из файла и переносит их в переменную или создает файл и записывает в этот файл строку. Ис­пользует формат:

file_str(Filename, Text) /* (i. o), (i, i) */

Если перед вызовом file_str переменная Text свободна, file_str читает символы из файла Filename пока не встретится символ конца файла ( обычно Ctrl-Z ). Содержимое файла Filename пересылается в переменную Text. Например, вызов:

file_str("t. dat". Myext)

свяжет Myext с содержимым файла Т. DAT. При этом строка может со­держать символы возврата каретки. Читаемый файл не может превы­шать 64 Кбайт в длину. Если файл имеет объем более 64 Кбайт, file_str возвратит сообщение об ошибке.

Если Myext связан., с текстом из "t.dat", file_str("t.bak", Myext) создаст файл с именем Т. ВАК, который содержит текст из "t. dat".

Предикат inkey читает символ с клавиатуры и имеет такой фор­мат:

inkey(Char) /* ( о ) */

Если, когда вызывается inkey, клавиша нажата (или содержится в буфере клавиатуры), inkey возвратит аргумент, которому присвое­но значение клавиши. Если ни одна клавиша не нажата, inkey немедленно потерпит неудачу.

Предикат keypressed проверяет была ли нажата клавиша на кла­виатуре и имеет формат:

keypressed

Предикат keypressed завершается успешно, если клавиша нажата или присутствует в буфере клавиатуры. Клавиша из буфера не удаля­ется.

Предикат unreadchar помещает символы во внутренний буфер клавиатуры и имеет формат:

unreadchar ( Char) /* ( i ) */

Размер этого буфера равен 128 байтам. Если он переполняется, unreadchar возвратит сообщение об ошибке.

Примеры. Следующие примеры демонстрируют, как можно использо­вать стандартные предикаты ввод для работы со сложными структурами данных и вводимыми списками.

1. Программа показывает, как использовать readIn и извлекать сложные структуры данных из входных строк.

domains

person = р(name,age, teno, job)

age = integer

telno,name,job = string

predicates

readperson (person)

run

goal

run.

clauses

readperson(p(Name,Age,Teno,Job)) :-

write ("Which name ?"), readln(Name),

write ("Job ?"), readln(Job),

write ("Age ?"), readln(Age),

write ("Telephone no?"), readln(Telno).

run : -

readperson (P),nl,wrlte(fi),nl.nl,

write("Is this compound object OK (y/n)"),

readchar (Ch),Ch='y'.

run : -

nl. nl, write("Alright, try again”), nl, nl, run.

2. В данном примере показано использование предиката readint для чтения целых чисел и преобразования их в список. Он читает одно целое число на строке, пока вы не введете не целое (клавишу X). После этого readint потерпит неудачу, и Турбо Пролог выведет список на экран.

domains

list = integer*

predicates

readlist (list)

goal

makewindow (1, 7, 7,"Integer List", 5, 5, 15, 70),

write("Type in a column of integers,liket this:",

"\n\n integer (pres ENTER)\n integer (pres ENTER) \n",

"etc \n\n Type К (pres ENTER) to end the list. \n\n"),

readlist(TheList ),

write("\nThe list is: ", TheList).

clauses

readlist([H| T]) :-

write("\16"), /* Печать символа-приглашения */

readint(H), !,

readlist(T).

readlist( [ ] ).

4. 3. Открытие и закрытие файлов

Следующие разделы описывают стандартные предикаты для открытия и закрытия файлов.

Предикат openread/2. Предикат openread открывает файл dosfilename для чтения, используя формат:

openread (symbolicfilename, dosfilename) /* (i. i) */.

Турбо Пролог обращается к открытому файлу по символическому имени symbolicfilename. Если файл не может быть открыт, то Тур­бо Пролог выдаст сообщение об ошибке.

Предикат openwrite. Предикат openwrite открывает dosfilenane для записи и имеет формат:

openwrite (symbolicfilename, dosfilename) /* (i, i) */

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

Предикат openappend. Предикат openappend открывает файл dosfilename для записи в конец файла. При этом используется формат:

openappend (symbolicFilename, dosfilename) /* (i, i) */

Если файл не найден, Турбо Пролог сообщит об ошибке.

Предикат openmodify. Предикат openmodify открывает файл DosFileName и для записи и для чтения. Он имеет формат:

openmodify (Symbol icFileName, DosFileName) /*(i, i) */

Если система не может открыть DosFileName, выдается сообще­ние об ошибке. Для заполнения файла с произвольным доступом пре­дикат openmodify может использоваться вместе со стандартным пре­дикатом filepos.

Предикат filemode. При открытии файла в текстовом режиме предикат filemode устанавливает указанный файл в текстовый или двоичный режим, используя формат:

filemode (SymbolicFileName, FileMode) /* (i,i) */

Если FileMode = 0, файл SymbolicFileName устанавливается в текстовый режим; если FileMode = 1, то он устанавливается в дво­ичный режим.

В текстовом режиме при записи к новым строкам добавляются символы ' возврат каретки ' /' перевод строки ', а при записи пара символов ' возврат каретки '/' перевод строки ' интерпретируется, как новая строка.

'Возврат каретки' = ASCII 13

'Перевод строки' = ASCII 10

В двоичном режиме никаких преобразований не производится. Для чтения двоичного файла вы можете использовать только предикат readchar.

Предикат closefile закрывает указанный файл и использует фор­мат:

closefile (SymbolioFtleName) /*(i)*/.

Этот Предикат завершается успешно, даже если файл не был открытым.

Предикат readdevice. Предикат readdevtce переопределяет текущее устройство чтения или выдает его имя. Предикат имеет формат:

readdevtce (SymbolicFtleName) /*(i),(o) */

Предикат readdevtce переопределяет текущее устройство чте­ния, если переменная SymbolicFileName определена и файл открыт для чтения. Если SymbolicFileName является свободной переменной, то readdevioe присвоит ей имя текущего активного устройства чте­ния.

Предикат writedevtce. Предикат writedevtce либо назначает или позволяет получить имя текущего устройства записи. Он имеет формат:

wrttedevtoe (SymbolicFileName) /* (i,о) */

Предикат wrttedevioe переопределит устройство записи, если указанный файл открыт для записи или добавления. Если переменная SymbolicFileName свободна, wrltedevice присвоит ей имя текущего активного устройства записи.

Примера

1. Следующая последовательность открывает файл MYDATA. FIL для записи, затем направляет весь вывод, порождаемый операторами между двумя предикатами writedevice в этот файл. MYDATA.FIL соответствует символическому имени destination, появляющему­ся в описании домена file.

domains

file=destination

goal

openwrite(destination,"mydata.fil").

wrttedevice(destination)], file

/* перенаправление вывода в файл MYDATA.FIL */

.

.

.

writedevice( screen),

/* перенаправление вывода на экран */

2. Данная последовательность направляет весь вывод, возни­кающий между двумя предикатами writedevice, на устрой­ство печати. Устройство печати открывать не нужно, так как оно управляется операционной системой.

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

writedevice(destinatJon)], file

/ * направление вывода на печать */

.

.

.

writedevice(screen),

/* направление вывода на экран */

3. Программа предназначена для создания программы, которая помещает символы, набранные на клавиатуре, в файл ДОС TRYFILE. ONE. Набираемые символы не выводятся на экран дисп­лея.

domains

file = myfile

predicates

readloop

goal

write("this program reads your input and writes it to TRYFILE. ONE\n",

openwri te(myfile,"tryf1le. one"),

writedevice(myfille),

readloop,

closefile(myfile),

write("Your input has been transferred to the file TRYFILE. ONE").

clauses

readloop: -readohar(X),X<>'#" ,! ,write(X), readloop.

readloop.