Во Флэнг включены два
типа данных с прямым
доступом к элементам -
векторы (с доступом по номеру)
и таблицы (с доступом по ключу). Векторы Флэнга близки по конструкции
классу ArrayList в Java.
Работу с векторами продемонстрируем на примере следующего диалога с
Флэнг-системой:
?- v := newVector([1,2,3,4,5]);
true
?- ^v;
(1, 2, 3, 4, 5)
Создаем новый вектор, и присваиваем его атому v. Для
порождения вектора
используется встроенная
функция newVector/1.
Аргументом является список элементов вектора. Добавим в вектор
новый элемент:
?- vAdd(^v, "six");
(1, 2, 3, 4, 5, "six")
Возьмем у вектора значение второго элемента:
?- vGet(^v, 2);
3
Обратите внимание, что нумерация элементов вектора
начинается с нуля.
Изменим теперь значение
третьего элемента:
?- vSet(^v, 2, "three");
"three"
?- ^v;
(1, 2, "three", 4, 5, "six")
Продемонстрируем рекурсию (цикл) по элементам вектора.
Следующая
программа
заменяет элементы вектора, являющиеся цифрами, на названия цифр:
numword(0) :- ноль; numword(1) :- один; numword(2) :- два; numword(3) :- три; numword(4) :- четыре; numword(5) :- пять; numword(6) :- шесть; numword(7) :- семь; numword(8) :- восемь; numword(9) :- девять; numword(X) :- X;
words(V, 0) :- V; words(V, I) :- vSet(V, I-1, numword(vGet(V, I-1))), words(V, I-1) ;
Названия цифр представлены атомами.
Внимание, для правильного отображения
символов кириллицы во Флэнг-системе необходима правильная установка
кодировки по
умолчанию. Для установки кодировки по умолчанию используется встроенная
функция defaultEnc/1.
Последнее правило numword/1
оставляет неизменными те элементы вектора, которые не являются цифрами.
Первый аргумент функции words/2 - вектор, элементы
которого меняются. Второй
аргумент - счетчик элементов.
?- ^v;
(1, 2, "three", 4, 5, "six")
?- words(^v, vLength(^v));
(один, два, "three", четыре, пять, "six")
Функция vLength/1
возвращает текущую длину вектора. Определение функции words/2
-
пример явной ("прямолинейной") рекурсии по элементам вектора. Более
гибкие механизмы обработки элементов векторов возможны с использованием
перечислений.
Важность векторов объясняется тем, что наряду со
списками
векторы во Флэнге
используются для создания содержимого XML-элементов. Определим функцию,
значением
которой является XML-терм:
pushkin145() :- <book> AП-145 <author> А.С. Пушкин </author> <title> Евгений Онегин </title> </book> ;
В XML-терме в теле правила содержимое элемента book
состоит из пяти
элементов:
- Строка AП-145
- Элемент <author>А.С.
Пушкин</author>
- Строка, состоящая из пробелов и
переводов строки
между
элементами
<author>А.С. Пушкин</author> и <title>Евгений
Онегин</title>
- Элемент <title>Евгений
Онегин</title>
- Строка, состоящая из пробелов и
переводов строки
между
элементом
<title>Евгений Онегин</title> и закрывающим тегом:
</book>
Теперь
?- getXConts(pushkin145());
[" AП-145 ", <author> А.С. Пушкин </author>, " ", <title> Евгений Онегин </title>, " "]
Встроенная функция getXConts
возвращает содержимое XML-терма. В данном случае это пятиэлементный
список. Флэнг-интерпретатор
в целях компактности при выводе на консоль заменяет символы перевода
строк на пробелы. При записи
же в файл первоначальная структура строк сохраняется.
Для формирования содержимого элементов могут
использоваться и
векторы. Поэкспериментируем с простой функцией
element(X) :- <element>_X;</element>;
Эта функция формирует XML-терм с именем element,
используя свой
аргумент как содержимое
XML-элемента.
Теперь:
?- element(["1",1+1,"3"]);
<element>123</element>
При формировании содержимого элементы списка
конвертируются в строковый
формат,
поэтому в качестве элементов списка можно использовать любые
Флэнг-выражения.
Совершенно также функция element работает и на векторе:
?- element(^v);
<element>одиндваthreeчетырепятьsix</element>
Здесь используется вектор, который мы строили выше.
Возможно и смешение
векторов
и списков:
?- element([v^, " ", 1, [2, " ", 3], 4]);
<element>одиндваthreeчетырепятьsix 12 34</element>
Обратите внимание, что при формировании XML-терма
вложенные списки
"разворачиваются".
Аналогично разворачиваются и вложенные вектора:
?- element(newVector([1,2,3]));
<element>123</element>
?- element(newVector([1,newVector([2]),[3]]));
<element>123</element>
На практике такая "всеядность" Флэнга при
формировании
содержимого
XML-элементов
оказывается очень полезной. Это позволяет в разных ситуациях
пользоваться разными
структурами данных и даже смешивать разные структуры в одном элементе.
|