Організувати дії, що повторюються можна за допомогою рекурсивного предикату Repeat.
Означення предикату має вид:
Repeat .
Repeat :- Repeat .
Предикат використовують в таких процедурах, де немає предикатів з декількома розв’язками, проте необхідно повторювати дії за допомогою механізму звороту.
Приклад: Написати програму, що обчислює корінь квадратний для кожного введеного числа.
Predicates
Repeat
Do
Control (integer)
Goal
Do.
Clauses
Repeat.
Repeat :- Repeat.
Do:- repeat, readint(N), control(N).
Сontrol (N):- N=0;
K= sqrt (N), write (K), nl, fail.
Кожний раз після обчислення коріння механізм звороту повертає керування на предикат Repeat. Предикат може пере узгоджуватися скільки – завгодно раз, бо компілятор перетворює просту рекурсію на ітерацію. Програма закінчить свою роботу по вводу 0.
Предикат Repeat невідомий Прологу, тому програміст повинен сам дати означення предикату. Предикат не зобов’язаний мати вказане ім’я.
Наприклад: Clauses
r.
r :- r.
4.4.5 МІРКУВАННЯ ПРО ТЕ, ЯК ТРЕБА ПИСАТИ ПРОГРАМУ
Програму на Пролозі пишуть за таким планом:
1. Описати факти, які подано у завданні.
Для цього треба:
Ø Визначити об’єкти і відношення між об’єктами.
Ø Визначити за мнемонікою функтор предиката для факту і типи даних для аргументів предикату.
2. З'ясувати, що потрібно знайти в завданні, і які для цього потрібні укрупнені дії.
3. Визначити предикат для кожної дії.
Для цього треба:
Ø Визначити функтори предикатів.
Ø Визначити для кожного предикату вхідні і вихідні дані.
4. Визначити метод рекурсії для повторюваних операцій у кожному предикаті. Використовуйте механізм звороту там, де це можливо.
4. При написанні програми треба визначити призначення кожного правила і факту, призначення гілок правил.
5. ОБРОБКА РЯДКІВ
5.1. ЗАГАЛЬНІ ВІДОМОСТІ
У Пролозі розглядаються типи: String для рядків та Symbol для ідентифікаторів.
Об’єкти даних доменів String та Symbol містять дані і методи, які працюють з цими даними. Тобто для рядків існують ряд стандартних предикатів - методів, які оброблюють дані цих доменів.
Типи String та Symbolсумісні і автоматично перетворюються друг в друга, якщо довжина рядку String не виходить за дозволену для рядку типу Symbol. Пролог дозволяє працювати з рядками типа string довжиною <= 64 КБ.
Рядок типу String може містити між лапками будь-які символи. Наприклад, ”Пролог V 2.0”.
Завдяки використанню керуючого символу ”\” всередині рядка типу String, можна записувати коди символів, будь-які керуючі символи. Наприклад,“\65\13”.Символи “\n”переводять курсор в начало наступного рядку.
Рядок типу Symbol записується за правилами запису ідентифікатора. Рядок записується без лапок, починається з маленької англійської букви чи підкреслення містить англійські букви, цифри та підкреслення. Довжина рядку типу symbol <= 250.
Використання констант типу String робить Exe.програми великими. Скільки раз константа зустрічається в програмі, стільки разів вона резервується в пам'яті. Тип Symbol – зберігається як рядок таблиці і Пролог звертається до цього рядка за індексом. У таблиці рядок зберігається один раз.
В Пролозі типи String і Symbol не сумісні з типом Char.
5.2. СТАНДАРТНІ ПРЕДИКАТИ ОБРОБКИ РЯДКІВ
Для роботи зі стандартними предикатами треба знати, які аргументи повинні бути конкретизованими при виклику предикату, і які повинні бути вільними. Для цього використовуються наступні позначення:
( і ) input (вхідні параметри);
(o) output (вихідні параметри).
Вхідні і вихідні аргументи певного предикату називають потоком параметрів.
Стандартні предикату обробки рядків працюють в декількох режимах. Тобто, кожний предикат обробки рядків може об’єднувати в собі декілька функцій. Для роботи кожної функції використовують свій варіант потоку параметрів. Таким чином, робота певної функції предикату залежить від варіанту потоку параметрів(конкретизації аргументів).
Для всіх предикатів роботи з рядками працюють наступні правила:
- якщо предикат повертає значення істинна, то при виконанні предикату вільні змінні конкретизуються значенням, інакше змінні не одержують значення;
- від порожнього рядка не можна відокремити частину, тому предикат повертає неправду;
- якщо будь – яку дію виконати не можна, то предикат повертає неправду.
Предикати побудови, контролю та розподілу рядків
Предикати можуть відокремлювати частину рядку, приєднувати рядок чи символ до початку іншого рядку, перевіряти з чого починається або чим закінчується рядок.
Предикат Frontchar (Рядок, Символ, Залишок)
(string, char, string)
Предикат працює з першим символом рядку.
Режими роботи предиката залежать від потоку параметрів, тобто від конкретизації змінних:
1) (і, o, o) поділяє рядок на перший символ і його залишок.
Наприклад: do: - readln (S), frontchar (S, C, R), write (С,” ”,R).
При S = ”Prolog” змінні одержать C=’P’, R=”rolog”.
При S = “” предикат повертає fail.
2) (o, i, i) приєднує символ до початку рядка
Наприклад: do: - readchar(S1), readln (S2), frontchar (S, S1, S2), write(S).
При S1=’P’, S2=”ascal” одержимо S=”Pascal”.
3) (і, і, o) перевіряє, чи починається рядок із зазначеного символу.
Приклад1: do(Str): - frontchar (“Prolog”,'P',R), write (“Так”).
Предикат повертає R=”Prolog
Приклад2: do(Str): - frontchar (“Prolog”,'G',R), write (“Так”).
Предикат повертає fail.
1) (і, o, і) перевіряє, чи дорівнює залишок рядка після відділення першого символу, зазначеному.
Приклад1: do: - frontchar (“Пролог”,C , ”ролог”), write(“Так ”).
Предикат повертає C=’P’.
Приклад2: do: - frontchar (“Пролог”,C , ”лог”), write(“Так ”).
Предикат повертає fail.
2) (i, i, i) перевіряє, чи складається рядок з вказаних частин.
Приклад1: do: - frontchar (“Пролог”,’П’ , ”ролог”), write(“Так ”).
Предикат повертає True.
Приклад2: do: - frontchar (“Пролог”,’П’ , ”ол”), write(“Так ”).
Предикат повертає fail.
Треба пам’ятати, що другий аргумент предикату має тип char. Тому для застосування змінної типу char у предикатах, що працюють з типом string, використовуйте предикат перетворення типу даного str_char.
Предикат Fronttoken (Рядок, Лексема, Залишок)
(string, string, string)
Будемо називати лексемою рядок англійських символів, який має певний зміст для того контексту, в якому він вживається. За даним означенням лексемою буде слово природної мови.
Предикат працює з першою лексемою рядку. Предикат не працює з кирилицею. Якщо рядок починається з пропуску, то пропуск відкидається.
Режими роботи предиката залежать від потоку аргументів, тобто від конкретизації змінних:
1) (і, o, o) розділяє рядок на перше слово і його залишок. Пропуск переноситься в залишок рядку.
Приклад1: Fronttoken (“Студент здав іспит”, W, R)
Предикат повертає W = “Студент”, R = “ здав іспит”.
Приклад2: Fronttoken (“”, W, R)
Предикат повертає fail.
2) (o, і, і,) приєднує слово до початку рядка. Не вставляє пропуск між словом і рядком.
Наприклад: Fronttoken (Str, “Студент”, “ здав іспит”)
Str = “Студент здав іспит”.
3) (і, і, o) чи починається рядок із зазначеного слова.
Приклад1: Fronttoken (“Студент здав іспит”, ”Студент”, R).
Предикат повертає R = “ здав іспит”
Приклад2: Fronttoken (“Студент здав іспит”, ”Студ”, R).
Предикат повертає fail.
4) (і, o, і) перевіряє, чи дорівнює залишок рядка зазначеному.
Приклад1: Fronttoken (“Студент здав іспит”, W, “ здав іспит”)
Предикат повертає W = ”Студент”
Приклад2: Fronttoken (“Студент здав іспит”, W, “ здав”)
Предикат повертає fail.
5) (і, і, і) перевіряє, чи дорівнює рядок зазначеним частинам, де частини – перше слово рядка і залишок.
Приклад1: Fronttoken (“Студент здав іспит”, ”Студент”, “ здав іспит”). Предикат повертає TRUE.
Приклад2: Fronttoken (“Студент здав іспит”, ”Студент”, “ іспит”). Предикат повертає fail.
Предикат Frontstr (Кількість символів, Рядок, Рядок1, Рядок2)
(integer, string, string, string)
( і, і, о, о)
Предикат відокремлює зазначену кількість символів від початку рядка. Відокремлений рядок заноситься в другий аргумент, а залишок заноситься в третій аргумент.
Наприклад: frontstr (5, “Програмування”, First, End)
Предикат повертає: First = „Прогр”, End = „амування”
Предикат Concat (Str1, Str2, Str)
(string, string, string)
Предикат працює з рядками, без ознаки що це за рядки. Для роботи предикату потрібно хоча б два конкретизованих аргументи:
1) (і, і, o) відбувається з'єднання рядків за принципом Str1+Str2 = Str.
Наприклад: concat (“V ”, “2.0”, Str)
Str = “V 2.0”
2) (і, o, і) виділяється маскою(рядком) початок іншого рядку.
Приклад1: concat (“Pr”, М, “Prolog”), де маска “Pr”.
Предикат повертає М = “olog”
Приклад2: concat (“PР”, М, “Prolog”), де маска “PР”.
Предикат повертає fail.
3) (o, і, і) виділяється маскою кінець рядку
Приклад1: concat (R, “віт”, “світ”). R = ”с”.
Приклад2: concat (R, “вік”, “світ”). Предикат повертає fail.
4) (i, i, i,) перевіряє, чи складається рядок із зазначених частин.
Приклад1: concat(“с”, “віт”, “світ”). Предикат повертає true.
Приклад2: concat(“г”, “віт”, “світ”). Предикат повертає fail.
Предикат контролю ідентифікатору
Предикат Isname (Рядок)
(symbol)
( і )
Предикат перевіряє, чи побудований рядок за правилами ідентифікатору. Ідентифікатор складається з англійських букв, цифр і знаку підкреслення і має довжину <=250. Ідентифікатор починається буквою або знаком підкреслення.
Предикат ігнорує пропуски, що стоять на початку рядку або в кінці.
Наприклад: isname (f3d) предикат повертає TRUE;
isname(2rtb) предикат повертає FAIL.