
- •Язык программирования турбо пролог
- •4.4. Переопределение стандартного ввода-вывода
- •4.5. Работа с файлами
- •5. Внутренняя база данных турбо пролога
- •5.1. Объявление внутренней базы данных
- •5.2. Обновление внутренней базы данных
- •5.3. Занесение фактов во время исполнения.
- •5.4. Удаление фактов во время выполнения программы
- •506 Type Error: The functor does not belong to the domain (функтор не относится к данному домену)
- •5.5. Чтение новых фактов иэ файла во время выполнения программы
- •5.6. Сохранение базы данных во время работы программы
- •6. Трассировка и отладка пролог программ
- •6.1. Синтаксическая проверка
- •6.2. Трассировка
- •6.2.1. Директивы трассировки
- •6.2.2. Трассировка в режиме оптимизации: shorttrace
- •6. 2. 3. Трассировка предикатов
- •6.2.4. Предикат trace
- •6.2.5. Диалоговое управление трассировкой
- •6.3. Директивы компилятора и отладка
- •6.4. Сообщения об ошибках во время выполнения программы
- •6.5. Опции компилятора из меню
- •7.Заключение
- •8. Литература:
- •Содержание:
Методические указания
Язык программирования турбо пролог
ВВЕДЕНИЕ
Язык программирования Пролог был создан в конце 60-х годов в Марсельском университете под руководством А. Колмероэ в результате работы над проектом по созданию системы анализа и понимания естественного языка. В начале Пролог использовался в основном для доказательства теорем и был основан на методе резолюции А. Робинсона. Первый интерпретатор Пролога был написан П. Русселем в 1973 и оказал сильное влияние на своих преемников. Дальнейшее развитие языка (до 1980 г.) было связано с формированием его синтаксиса и семантики. В результате в качестве стандарта была принята версия, разработанная под руководством Д. Уоррена в Эдинбурге.
В настоящее время язык Пролог находит основное применение при создании различных интеллектуальных, в частности, экспертных систем, для создания интерфейсов с естественного языка, при автоматизации проектирования и т. п. Помимо указанных применений, связанных с приложениями искусственного интеллекта, язык Пролог имеет самостоятельную ценность как язык программирования.
ОПИСАНИЕ: ТУРБО ПРОЛОГ СИСТЕМ
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.