Секція domains Пролог-програми
У секції domains описуються будь-які нестандартні домени, використовувані для аргументів предикатів. Домени в Пролозі є аналогами типів в інших мовах. Основними стандартними доменами Пролога є:
char – символ в одиночних лапках (наприклад, 'а');
integer – ціле від -32768 до 32767 (переводиться в дійсне автоматично, якщо необхідно);
real – дійсне (наприклад, -68.72, бе-94, -791е+21);
string – послідовність символів у подвійних лапках (наприклад, "натисніть ввід");
symbol – або набір латинських букв, цифр і символів підкреслення, у якому перший символ - прописна буква (наприклад, n_fax); або послідовність символів, що містить пробіли або починається з малої літери, укладена в лапки (наприклад, "Список СУБД").
file – символічне ім'я файлу, що починається з прописної букви.
Крім стандартних доменів користувач може використовувати свої. Для цього в області оголошення доменів можна використовувати наступні формати:
а) name = stanDom,
де stanDom – один зі стандартних доменов: int, char, real, string або symbol; name – одне або кілька імен доменів. Наприклад, fio=symbol або year, height=integer;
б) mylist = elementDom*,
де mylist – область, що складається зі списків елементів з області elementDom, що може бути визначена користувачем або мати стандартний тип. Наприклад, number5th = integer* або letter = char*;
в) myCompDom=functor1(d11,...,d1n); functor2(d21,..., d2n); ... functorm(dm1,...,dmq),
де myCompDom – область, що складається зі складених об'єктів, описуваних вказівкою функтора та областей для всіх компонентів. Права частина такого опису може визначати кілька альтернатив, розділених ";" або "or". Кожна альтернатива повинна містити єдиний функтор, і опис типів для компонентів dij. Наприклад,
auto = car(symbol,integer),
packing = box(integer, integer, integer); bottle(integer)
описує дві області auto і packing. Область auto відповідає двокомпонентній структурі з функтором car, а область packing відповідає одній з двох можливих структур box і bottle, що розрізняються не тільки іменами, але і кількістю компонентів.
г) file = name1; name2 ; ... name_n
використовується, коли необхідно посилатися на файли по їхніх символічних іменах.
Наприклад, розглянемо побудову структури даних для збереження інформації про комп'ютери. При цьому кожен комп'ютер буде розглядатися як набір вхідних у нього пристроїв, серед яких можуть бути: процесори з указівкою їхнього найменування і частоти, вінчестери із указівкою їхнього обсягу і фірми виготовлювача, також монітори визначеного типу. Область визначення доменів для цього прикладу буде мати вигляд
domains
name , firm , type = symbol
freq , vol = integer
device = processor(name, freq); disk(firm, vol); monitor(type)
computer = device*
У цьому описі домен computer є списком елементів типу device, тобто кожен елемент цього списку може мати структуру типу або processor, або disk, або monitor, що містять одну або два компоненти, кожна з яких має стандартний символьний чи цілий тип.
Секція predicates
У секції predicates описуються предикати і типи (домени) аргументів цих предикатів. Імена предикатів повинні починатися з рядкової латинської букви, за якої слідує послідовність букв, цифр і символів підкреслення (до 250 знаків). В іменах предикатів не можна використовувати символи пробілу, мінуса, зірочки, зворотної (і прямій) риски. Оголошення предикатів має форму:
predicates
predicateName_1 (domen_11, domen_12,..., domen_1m)
predicateName_n (domen_n1, domen_n2,..., domen_nk)
де domen_ij – або стандартні домени, або домени, оголошені в секції domains. Оголошення домену аргументу й опис типу аргументу – те саме. Кількість доменів (аргументів) предиката визначають арність (розмірність) предиката. Предикат може не мати аргументів і мати тільки ім'я. Звичайно вибирається таке ім'я предиката, щоб воно відображало визначений вид взаємозв'язку між аргументами предиката. Приклад опису предикатів:
predicates
student( string,real)
start
good_student( string)
Можна використовувати кілька описів того самого предиката. При цьому всі описи повинні слідувати один за іншим і повинні мати однакове число аргументів. Нехай потрібно визначити відношення між трьома аргументами, перші два з яких відповідають доданкам, а третій – сумі двох перших. Цей предикат може бути описаний у наступному виді:
predicates
add(integer,integer,integer)
add(real,real,real)
і дозволить його аргументам набувати значень як з області цілих, так і дійсних чисел.
Секція clauses
У секції clauses розміщаються факти і правила, з якими буде працювати Пролог, намагаючись довести мету програми.
Факт – це твердження про існування деякого відношення між аргументами, що позначається ім'ям предиката. Факти – це фрази без умов і вони містять твердження, що завжди абсолютно вірні. Форма запису фактів:
clauses
predicate_Name_1 (term_11, term_12,..., term_1k). ,
...
predicate_Name_N (term_N1, term_N2,..., term_NL).
де predicate_Name_1 – імена предикатів, описаних у секції predicates, a term_11, ..., term_1k – аргументи предикатів (терми), кількість яких повинна відповідати арності опису предиката. Наприклад, факти, що визначають відношення, задане предикатом student, можуть мати вигляд:
clauses
student("Петров" ,4.5).
student("Сидоров" ,3.75).
Правила містять твердження, істинність яких залежить від деяких умов (підцілей), що утворять тіло правила. У Пролозі правила представляються у вигляді
Заголовок :- Підціль_1 , Підціль_2 , ... , Підціль_N. ,
де позначення “:-“ читається як “якщо”, а Заголовок має таку ж форму, як і факт. Тіло правила – це список підцілей, розділених комами. Кому розуміють як кон'юнкцію і читають як “і”. Приклад запису правила
good_student(Name) :- student( Name , В ) ,В > 4.
Для того щоб заголовок правила виявився істинним, необхідно, щоб кожна підціль, що входить у тіло правила, була істинною. Змінні в заголовку правила, квантифіковані універсально. Це означає, що правило, заголовок якого містить змінні, буде істинним для будь-яких термів, що відповідають підцілям правила. З іншої сторони змінні, що входять тільки в тіло правила, квантифіковані екзістенціально. Якщо врахувати таку квантифікацію, то наведене вище правило можна прочитати так:
Для будь-якої особи Name, Name є гарним студентом, ЯКЩО існує середній бал В такий, що Name є студентом із середнім балом В і середній бал В більше 4.
Множина правил, заголовки яких містять однакові імена предикатів і кількість аргументів, називаються процедурою. У Пролозі предикати визначаються (реалізуються) за допомогою процедур. Так наступні два правила
max(Х, Y, X) :- Х >=Y.
max(Х, Y, Y) :- Х < Y.
реалізують процедуру знаходження найбільшого з двох чисел, обумовлену предикатом виду max(number_1, number_2, max_number). Вважається, що між цими двома правилами неявно присутній напевний сполучник “або”.
Секція goal
У секції goal задається внутрішня мета програми. Це дозволяє програмі запускатися незалежно від середовища розробки. Якщо внутрішня мета включена в програму, то Пролог виконує пошук тільки одного першого рішення, і зв'язані з змінними значення не виводяться на екран, якщо не передбачити застосування операторів виводу інформації.
У систему Пролог включене більш ніж 200 вбудованих стандартних предикатів і більше дюжини стандартних доменів. У випадку використання цих предикатів і доменів немає необхідності оголошувати їх у програмі.
Розглянемо приклад програми, у якій задана внутрішня мета і використовується звертання до стандартних предикатів:
/* Програма 1.2 */
predicates
hello (string)
goal
hello (_).
clauses
hello (Name):- write("Please, type your name "), readln(Name), nl, write("Welcome ", Name).
У цій програмі запитується Ваше ім'я, а потім воно виводиться на екран.
Перелік і призначення стандартних предикатів наведений у додатку А.
Однак найчастіше метою є складний запит до програми. Для доведення якої-небудь складної мети Пролог повинний довести всі його підцілі, створивши при цьому необхідну множину зв'язаних змінних. Якщо ж одна з підцілей помилкова Пролог повернеться назад і перегляне альтернативні рішення попередніх підцілей, а потім знову піде вперед, але з іншими значеннями змінних. Цей процес називається „пошук з поверненням”.
Секція database
Ключове слово database вказує на початок послідовності описів предикатів динамічної бази даних. Динамічна база даних є базою, у яку факти додаються під час виконання програми. Вимоги до описів предикатів такі ж, як і в секції predicates. Факти, що належать динамічній базі даних, обробляються відмінним від звичайних предикатів чином для того, щоб прискорити роботу з БД великого обсягу. Факти динамічної бази можуть модифікуватися протягом сеансу роботи, завантажуватися з дискового файлу за допомогою стандартного предиката consult або записуватися в дисковий файл за допомогою предиката save.