Для виклику функтору результуючого нового складного об'єкту, ми повинні змінити базовий опис книги:
book('The Ugly Duckling',author('Hans Christian','Andersen'))
В старому описі об'єкту:
book(title,author)
другий аргумент функтору book є author. Але старий опис
author = symbol
може тільки включати просте ім'я, тому його не можна застосовувати.
Ми повинні зараз специфікувати, що author є складним об'єктом, який включає ім'я та прізвище:
author(first_name,last_name)
Котре вимагає наступний опис:
domains
articles = book(title, author) ;
horse(name) ;
boat ;
bankbook(balance)
author = author(first_name,last_name)
title, author, name = symbol
balance = real
Коли використовуються складні об'єкти різного рівня, їх зручно зображати у вигляді дерева.
book
/ \
title author
/ \
/ \
firstname lastname
Речення домену описує тільки один рівень дерева, а не все дерево. Наприклад, книга з нашого прикладу не може бути описана наступним чином.
book=book(title,author(firstname,lastname))
5.6.Приклад, який ілюструє задання структури речення англійської мови.
Розглянемо приклад задання граматичної структури речення, використовуючи складний об'єкт. Найбільш просте речення має підмет і присудкову частину:
sentence = sentence(noun,verbphrase)
Де підмет є простим словом:
noun=noun(word),
а присудкова частина може мати або ж дієслово з пояснюючою частиною, або ж просто дієслово
verbphase=verbphrase(verb,noun);
verb(word)
verb = verb(word)
Використовуючи такий опис, речення 'Еllen owns the book.' може бути представлене
sentence(noun(ellen),verbphrase(verb(owns),noun(book)))
Відповідне дерево прийме вигляд
sentence
/ \
/ \
noun verbphrase
/ / \
/ verb noun
| | |
ellen owns the book
Подібний підхід може бути використаний при написанні блоку синтаксичного аналізу компілятора.
5.7.Опис змішаних складних об'єктів.
В цьому розділі ми розглянемо три різні типи опису доменів, які ви можете використовувати у ваших програмах. Ці описи дозволяють вам використовувати предикати, які:
мають аргумент , який може бути різного типу;
мають змінну кількість аргументів, кожний з яких окремого типу;
мають змінну кількість аргументів, деякі з яких можуть бути різного типу.
5.7.1.Аргументи, які можуть мати різний тип.
Для того, щоб дозволити предикату допустити аргументи різного типу, ви повинні додати опис функтору. Наприклад, в наступному прикладі фраза your_age, буде допускати аргумент типу age, який може бути стрічковим, цілим, дійсним.
predicates
your_age(age)
clauses
your_age(i(AGE)):-write(AGE)
your_age(r(AGE)):-write(AGE)
your_age(s(AGE)):-write(AGE)
тоді домен повинен бути наступним:
domains age = i(integer);
r(real);
s(string)
predicates your_age(age)
Поряд з тим Пролог не дозволяє наступні описи доменів:
domain
age = integer, real, string
5.7.2 Cписковий тип.
Припустимо, нам необхідно створити базу-довідник, в якій ми будемо зберігати дані про лекційні курси, які можуть читати професори. Її можна реалізувати наступною програмою:
predicates
teacher(symbol, symbol, symbol)
clauses
teacher(ed,willis,english).
teacher(ed,willis,math1).
teacher(ed,willis,hystory1).
teacher(mary,marker,english2).
teacher(mary,marker,math2).
teacher(cris,grim, geometry).
Тут в нас виникає необхідність повторювати прізвище для кожного предмету. Це марудно, тому краще використати тип списку. В наступному прикладі, аргумент classes, описаний як списковий тип.
domains
classes = symbol*
predicates teacher(symbol,symbol, classes)
clauses
teacher(ed, willis,[ english,math1, history1]).
teacher(mary, maker,[history2, math2 ]).
teacher(chris,grahm,[geometry]).
В цьому прикладі відмітимо опис DOMAINS :
domains
class = symbol*
Тут ми показуємо, як представляються в Пролозі списки.
Символ (*) означає, що class є символьним списком. Аналогічно можна визначити список цілих чисел:
domains
integer_list = integer*
5.8.Порівняння складних об`єктів.
Складні об'єкти повинні зрівнюватись на еквівалентність з предикатами, визначеними програмістом, подібно до предикату are_equal із наступної програми:
domains
d = pair(integer, integer) ;
single(integer) ;
none
predicates
are_equal(d, d)
clauses
are_equal(X, X).
Задамо ціль goal: are_equal(5,4). Бачимо помилку в визначенні домену. Для фіксації проблеми додамо опис:
are_equal(integer, integer).
5.9.Узагальнення.
1.Програма Прологу може містити наступну множину типів даних: простий або складний, стандартний або визначений користувачем.
2.Складні структури даних дозволяють об`єднувать окремі частини інформації в один об`єкт. Він складається з імені (функтора) і одного або більше аргументів.
3.Функтор Прологу не відповідає функціям традиційних мов програмування типу Паскаль. Він не викликає ніякої дії.
4.Складна структура даних може уніфікуватись з простою змінною, або з складним об`єктом, який має відповідну структуру. Знак “=“ використовується для уніфікації складних об`єктів.
Вправи.
5.1. Виберіть деяку форму задання бази даних, в якій містяться повідомлення про операції з кредитними карточками. Кожний запис повинен мати інформацію про прізвище особи, яка тратить гроші, про тип операції і кількість грошей. Напишіть програму, яка буде видавати значення кінцевої суми всіх операцій для конкретної особи.
5.2. Нехай нам потрібно створити базу даних про сім`ї, яка б дозволяла оперувати з наступною інформацією. Кожна сім`я складається з трьох компонент: чоловік, дружина і діти. Оскільки кількість дітей в різних сім`ях може бути різною, тому бажано їх задавати у вигляді списку, який складається з довільної кількості елементів. Кожного члена сім`ї в свою чергу можна задати структурою, яка складається з чотирьох компонент: ім`я, прізвище, дата народження і місце роботи. Інформація про роботу може бути такою - це або “не працює”, або вказівка на місце роботи і заробітної плати.
Напишіть терм, який би дозволяв:
а)посилатись на всіх Іванових;
б)посилатись на всі сім`ї, які мають трьох дітей.
Побудуйте запит:
а)який би дозволяв знаходити всіх заміжніх жінок, які мають не менше трьох дітей.
Побудуйте набір предикатів, який би дозволив використати наступні запити до бази даних:
а)знайти всіх людей із бази даних;
b)знайти всіх дітей, які народились в 1990 році;
с)знайти всіх дружин, які працюють;
g)знайти людей, які народились до 1960 року;
е)знайти загальний заробіток кожної сім`ї.
6. ІТЕРАЦІЯ І РЕКУРСІЯ.
6.1.Реалізація ітераційного процесу за допомогою бектрекінгу.
В цьому розділі ми розглянемо спочатку організацію циклічної обробки, а потім рекурсивні структури даних.
Пролог допускає тільки два типи повторних дій: бектрекінг і рекурсію. В програмі, зображеній на мал.6.1, показано використання бектрекінгу для реалізації циклу. На поставлений запит будуть друкуватись всі можливі рішення.
predicates
country(symbol)
print_countries
clauses
country(england).
country(france).
country(germany).
country(denmark).
print_countries :- country(X),
write(X), /* write the value of X */
nl, /* start a new line */
fail.
print_countries.
мал.6.1.
Перша фраза говорить: "Знаходячи розв'язок предикату cuntry(x), надрукувати країну Х