Скачиваний:
23
Добавлен:
22.05.2015
Размер:
137.73 Кб
Скачать

Списочные домены

Объявление списочных доменов осуществляется очень просто – надо справа от домена элемента списка указать звёздочку. Например:

domains

list = integer*.   % Список целых чисел L=[8,-36,-209,0]

ul = unsigned*.    % Список беззнаковых L=[8,36,209,0]

числа = real*.     % Список вещественных  L=[8.2,-36.189]

строки = string*.  % Список строк L=[“QW”,“Пролог”,”5t”]

символы = char*.   % Список символов L=[‘t’,’Ф’,’\61’]

Последний символ в списке символов указан посредством его ASCII-кода. Также легко создавать списки списков и т.д. Например:

domains

list = integer**.   % Список списков целых чисел

ul = unsigned**.    % Список списков беззнаковых целых

числа = real**.     % Список списков вещественных чисел

строки = string**.  % Список списков строк

символы = char**.   % Список списков символов

Visual Prolog содержит ряд списочных доменов, объявленных в классе core:

integer_list = integer*.

integer_list_list = integer_list*.

integer_list_list_list = integer_list_list*.

unsigned_list = unsigned*.

unsigned_list_list = unsigned_list*.

unsigned_list_list_list = unsigned_list_list*.

real_list = real*.

real_list_list = real_list*.

real_list_list_list = real_list_list*.

char_list = char*.

char_list_list = char_list*.

char_list_list_list = char_list_list*.

string_list = string*.

string_list_list = string_list*.

string_list_list_list = string_list_list*.

symbol_list = symbol*.

symbol_list_list = symbol_list*.

symbol_list_list_list = symbol_list_list*.

Полный перечень списочных доменов содержится в описании класса core.

Ввод-вывод списков

Ввод списка с клавиатуры или из файла осуществляется предикатом X=read(). Этот предикат ожидает ввода с клавиатуры терма X. Тип терма можно указать принудительно, с помощью предиката hasDomain(Domain,X). Если тип терма не указан, то Visual Prolog автоматически во время компиляции определяет тип терма на основе последующих операций над ним, производимых в исходном тексте. Если Пролог во время компиляции не может определить тип терма, то ему следует “помочь”, явно указав перед вызовом функции read() тип вводимых данных с помощью предиката hasDomain(Domain,X).

Для ввода списка целых чисел посредством предиката X=read() необходимо набрать с клавиатуры последовательность, например [7,8,1,2,0,-3,7] или любой другой, в которой элементы списка перечислены через запятую и взяты в квадратные скобки. После ввода списка с клавиатуры, он будет унифицирован с переменной X=[7,8,1,2,0,-3,7]. Для вывода списков можно использовать предикат write(X).

В этой лабораторной работе мы создадим не GUI-проект, а консольный проект. Это упростит выполнение примеров и задач. Консольное приложение стартует с предиката run().

Например, вот такая цель:

run():-init(),

   hasDomain(string_list,X),

   X=read(),clearInput(),

   write(X),nl,

   _=readchar().

позволяет ввести список строк с клавиатуры и для контроля вывести его на экран. Предикат clearInput() вызывать сразу после ввода с клавиатуры не обязательно, но желательно, так как он освобождает буфер клавиатуры от введённых данных. Если этого не делать, то данная программа выполнится, и окно консоли сразу закроется, так как предикат _=readchar(), стоящий в конце цели, выполнится без ожидания ввода с клавиатуры, ибо предикат ввода X=read() оставляет данные в буфере.

Пример 0. Определение длины списка целых чисел, вводимых с клавиатуры:

implement main

open core, console

constants

className = "com/visual-prolog/main".

classVersion = "$JustDate: $$Revision: $".

class predicates

len : (Elem* Список, unsigned Длина) procedure (i,o).

length : (Elem* Список, unsigned Накопитель, unsigned Длина) procedure (i,i,o).

clauses

classInfo(className, classVersion).

len([_|L],D) :- !, len(L,D1), D=D1+1.

len([],0).

length([_|L],T,D) :- T1=T+1, !, length(L,T1,D).

length([],D,D).

run():-init(),

   hasDomain(integer_list,X),

   X=read(),clearInput(),

   write("Список: ",X),nl,

   len(X,D),

   write("Длина списка = ",D),nl,

   length(X,0,D1),

   write("Длина списка = ",D1),nl,

   _=readchar().

end implement main

goal

   mainExe::run(main::run).

В этом примере длина списка определяется двумя способами. Первый способ использует нехвостовую рекурсию:

len([_|L],D) :- !, len(L,D1), D=D1+1.

len([],0).

Второй способ использует хвостовую рекурсию с дополнительным аргументом-счётчиком Накопитель, в котором накапливается текущая сумма до тех пор, пока список не станет пуст:

length([_|L],T,D) :- T1=T+1, !, length(L,T1,D).

length([],D,D).

Задача 0. Перепишите два предиката из примера 0 в виде функций.

Соседние файлы в папке Лабораторные работы