Программа на языке Турбо Пролог состоит из нескольких
разделов, каждый из которых имеет свое назначение. Всего в
ТП существует семь разделов, из которых только один (при
работе в Турбо-оболочке) или два (при создании автономной
программы) является обязательными. Наиболее часто
используются следующие разделы:
- раздел определения типов данных domains (необходим в
том случае, если в программе используются нестандартные
типы данных);
- раздел определения предикатов predicates
(необходим в том случае, если в программе используются
предикаты, определяемые пользователем);
- основной раздел clauses, содержащий факты и правила;
- раздел goal, в котором определяется цель (обязателен
в том случае, если предполагается автономное использование
Пролог-программы).
Кроме того существуют следующие разделы: database,
позволяющий использовать в Проллог-программах базы данных;
global domains и global predicates - применяемые при
построении многофайловых Пролог-программ.
Каждый раздел начинается с ключевого слова - названия
раздела. На последовательность разделов накладывается
единственное ограничение: разделы-описания объектов и
отношений должны располагаться в программе до их
использования.
Раздел clauses
Раздел clauses (предложения) является основным
разделом и представляет собой собственно программу на языке
Пролог. Раздел состоит из предложений, описанных в п.2.1.
Раздел domains
Раздел domains (мат. - область определения) содержит
описание новых типов данных, определяемых пользователем.
С целью повышения наглядности программы (см. описание
раздела predicates), рекомендуется переименовывать
стандартные наименования типов данных на наименования,
несущие смысловую нагрузку. Например:
domains
family, name = symbol
year = integer.
Здесь объявлены объекты трех типов: фамилии (family),
имена (name) и год (year). Первые два из них совпадают со
стандартным типом symbol, а последний - с целочисленным
типом данных.
Как видно из примера, каждая строка раздела domains
содержит описание одного типа объектов. В начале строки
указываются вводимые пользователем наименования типа,
перечисляемые через запятую, а в конце строки определяется
стандартный тип ТП, определяемый знаком равенства.
Кроме того, в разделе domains могут быть определены
перечисляемый и структурированные типы объектов. Перечисляемые
типы описываются при помощи строки, содержащей наименование
типа и (через знак равенства) значения объектов,
перечисляемые через точку с запятой. Например:
wday = monday, tuesday, wednesday, thurday, friday
side = north, west, south, east.
Структурированные объекты описываются при помощи
функтора ( наименования структуры) и типов его аргументов,
заключенных в скобки:
box = box ( inteder, inteder, inteder, inteder)
person = person ( fam, name, agesex).
В первом случае для описания аргументов использован
стандартный тип данных ТП, во втором - нестандартные.
Поэтому строке person в разделе domain должны
предшествовать описания используемых типов, например:
fam, name = symbol
age = integer
sex = man, woman.
Раздел predicates.
Раздел predicates ( предикаты) содержит описание
всех нестандартных предикатов, используемых в программе.
Каждая строка этого раздела должна содержать описание
одного предиката. Предикаты определяются своими именами и
аргументами. Имена предикатов должны начинаться со строчной
буквы, а аргументы должны соответствовать стандартным, или
определенным в разделе domains типам данных, и должны быть
заключены в скобки. Элементы раздела predicates
не являются предложениями, поэтому точка после поределения
предиката не нужна. Например:
predicates
person (family, name, year)
age (family, year).
В первом описанном предикате person первый аргумент
определяет фамилию, второй - имя человека, а третий - год
его рождения. Аргументы второго предиката age
(возраст) соответствуют фамилии и возрасту в годах
человека. Следует отметить, что подобное описание
предикатов при помощи нестандартных типов данных Family,
name, year гораздо нагляднее, чем их описание с
использованием стандартных типов данных:
person ( symbol, symbol, integer)
age ( symbol, integer).
Раздел goal.
Paздел goal является обязательным при написании
автономных Пролог-программ. При работе из оболочки ТП этот
раздел необязателен, т.к. оболочка ТП сама сгенерирует
запрос цели. При этом на экране появится окно диалога, в
котором будет находиться строка запроса цели с ключевым
словом "Goal". Пользователю необходимо только
сформулировать цель в виде одного ( или нескольких)
предикатов, определенных в программе, например:
Goal: age ( "Иванов", X)
Goal: person ( "Иванов", "Петр", 1972, man).
В первом случае Пролог-система сообщит возраст объекта
"Иванов" ( например, Х = 20) , а во втором случае ( т.к.
все аргументы конкретизированы, т.е. заранее определены) -
проверит истинность указанного предиката и сообщит
результат этой проверки (" Yes" или "No" ).
При написании автономной программы пользователь сам
должен позаботиться об отображении получаемого результата.
Для этого в цель, описываемую в разделе goal должны
быть включены предикаты вывода ( например, стандартные
предикаты ТП write или writef):
goal age ("Иванов", X), write ("Возраст",X," лет").
При этом на экране монитора в окне диалога появится
сообщение: "Возраст 20 лет".
Списки являются простейшей и наиболее распространенной
формой структурной организации данных в Прологе. Список
представляет собой последовательность произвольного числа
однотипных элементов. В качестве элементов списка могут
выступать любые объекты Пролога, в том числе и сами списки.
Единственным ограничением является требование того, чтобы
все элементы имели один и тот же тип. В ТП списки
ограничиваются квадратными скобками, например:
[оne, two, three ] ,
["May"," Yune"," Yuly"] ,
[ "Москва", "Рязань", "Солотча"].
Особое место в операциях над списками занимает пустой
список, который изображается при помощи двух скобок: "[]".
Список не является стандартным типом объектов ТП, а
представляет собой сложную, структурированную организацию
данных, поэтому перед его использованием в программе в
разделе domains обязательно необходимо объявить новый тип
данных. Для объявления списочного типа используется символ
"*" , который ставится после указателя типа элементов
списка, например:
domains
int_list = integer *
symb_list = symbol *
ssymb_list = symb_list *.
Первая строка раздела domains определяет новый тип
объектов int_list, представляющих собой список целых чисел,
вторая строка определяет тип symb_list, представляющий
собой список символьных выражений. Третья строка раздела
устанавливает тип ssymb_list объектов-списков, элементами
которых являются структурированные объекты типа списков
символьных выражений (список списков ). Для использования
новых типов данных в качестве аргументов в Пролог-программе,
необходимо в разделе predicates объявить их для соответству-
ющих предикатов. Например:
predicates
marks (symbol, int_list)
ancestors ( symbol, symb_list).
Для обработки списочных структур чаще всего
используются рекурсивные правила. Например, для определения
принадлежности элемента списку используется следующее
правило:
belong ( X, [X|_]).
belong ( X, [_|T]): - belong (X,T).
Предварительно в разделе predicates должен быть объявлен
предикат, например:
belong (integer, int_list),
при этом тип элементов списка второго аргумента должен
совпадать с типом первого аргумента.
В качестве примеров обработки списков приведем ряд
правил для определения предикатов, аргументами которых
являются списки:
1. Объединение списков L2 и L3 в один список L1:
conc([], L,L).
conc([X|L1], L2, [X|L3]) :- conc(L1,L2,L3).
2. Удаление элемента Х из списка L:
del(X,[X|T], T).
del(X, [Y|T], [Y|T1]) :- del(X,T,T1).
Третий аргумент предиката del - результирующий список.
3. Подсписок S списка L :
sublist (S,L):-
conc(_, L1, L), conc(S, _, L1).
4. Определение длины списка:
listlen([], 0).
listlen([_|T],N) :- listlen(T,N1), N = N1+1.
5. Вывод списка на экран по элементам:
typelist([]).
typelist([H|T]) :- write(H), nl, typelist(T).
6. Определение суммы элементов списка чисел L:
listsum([], 0).
listsum([H|T], Sum) :- listsum(T,S), Sum = H + S.
7. Oпределение наибольшего числа M в списке чисел L :
maxelm([M],M).
maxelm([X,Y|T], M) :-
maxelm([Y|T],E), max (X,E,M).
В последнем правиле используется нестандартный предикат
max, определяющий в качестве третьего аргумента наибольшее
из двух чисел, заданнных первыми двумя аргументами. Предикат
max определяется при помощи следующего правила:
max (X,Y,X):- X >= Y.
max (X,Y,Y):- X < Y.
|