| Флэнг является
универсальным языком, на
котором можно решать самые
разные задачи.
Однако Флэнг можно назвать и специализированным языком, поскольку все
его универсальные средства в первую очередь "заточены" под обработку
размеченной текстовой информации -
информации, представленной в формате языков XML и HTML. Во Флэнге в
полной мере использован тот факт,
что XML- и HTML-документы легко представимы в виде стандартных типов
данных логического
и функционального программирования - термов. Документы в этих форматах
имеют рекурсивную природу,
а рекурсия являются стихией функционального и логического
программирования.
Это превращает Флэнг в чрезвычайно удобное и эффективное средство
работы с размеченными документами.
В этой главке демонстрируются простейшие, базовые
средства
Флэнга, ориентированные на работу с размеченными
текстами. Более сложные и выразительные примеры будут рассмотрены в
последующих
главках. Сначала определим функцию, значением которой является
маленький HTML-документ:
greetings(Text) :- <html> <head><title>Приветствие</title></head> <body> <h1>_Text;</h1> </body> </html> ;
HTML-выражения (точнее, XML-выражения, поскольку
формируются по
правилам XML, а не HTML)
являются для Флэнга стандартными структурами данных. Будем называть их
XML-термами. Функцию
greetings(Text) можно назвать пераметрическим XML-документом.
Параметром
является переменная Text, которая вкраплена в html-текст. Стандартные
выражения Флэнга
могут включаться в XML-термы между символами '_' и ';'.
Внимание: в текущей версии Флэнга
XML-термы
допустимы только в теле правил.
В остальных случаях следует использовать представление термов в виде
стандартных структур (см. главку "XML-термы:
часть 2").
Сделаем Флэнг-системе запрос, подставив вместо
переменной
сакраментальное "Hello, World!":
?- greetings("Hello, World!");
<html> <head><title>Приветствие</title></head> <body> <h1>Hello, World!</h1> </body> </html>
Результатом функции является готовая html-страничка.
Мы ее можем
записать на диск:
?- writeHTML("hello.html", greetings("Hello, World!"), "w");
Флэнг создаст файл hello.html,
результаты
загрузки которого в броузер будут
весьма предсказуемыми. Функция
writeHTML(FileName, Term, Enc)
записывает
XML-терм (второй аргумент) на диск в формате HTML-документа. Аргументы
функции
FileName - имя html-файла, в который записывается XML-терм Term - записываемый XML-терм Enc - кодировка ("w" - сокращение для windows-1251).
Теперь рассмотрим несколько более сложную задачу,
которая состоит в
построении диагональной квадратной
матрицы (таблицы чисел) вида:
1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4
По диагонали - номера соответствующих строк, остальные
элементы матрицы
равны нулю.
Входным параметром является размер матрицы. Результат - html-файл,
рисующий таблицу.
Ясно, что для формирования матрицы в html нужно использовать элемент
table. Тогда
для матрицы, приведенной выще, имеем следующее html-представление:
<table> <tbody> <tr><td>1</td><td>0</td><td>0</td><td>0</td></tr> <tr><td>0</td><td>2</td><td>0</td><td>0</td></tr> <tr><td>0</td><td>0</td><td>3</td><td>0</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>4</td></tr> </tbody> </table>
Основная задача - формирование строки матрицы. Эту
задачу выполняет
функция row,
собирающая элементы строки в список:
row(N, M, N) :- []; row(M, M, N) :- [<td width="30">_M+1;</td> | row(M+1, M, N)]; row(I, M, N) :- [<td width="30">0</td> | row(I+1, M, N)];
Аргументы функции row(I, M, N) имеют следующий смысл:
I - счетчик по элементам строки (нумерация элементов от 0 до N-1) М - номер рисуемой строки (нумерация строк от 0 до N-1) N - размер матрицы
Функция последовательно добавляет элементы к списку,
начиная с пустого
списка
(это первое правило, когда считчик равен размеру матрицы). Если
добавляется диагональный
элемент (счетчик равен номеру строки), то используется второе правило.
Для остальных (нулевых)
элементов используется третье правило. Определение функции расчитано на
нумерацию строк от 0 до N-1 (так удобнее).
Обратите внимание, что из-за этого во втором правиле в качестве
диагонального элемента добавляется число M+1:
<td width="30">_M+1;</td>
Пример работы функции:
?- row(0, 1, 3);
[<td width="30">0</td>, <td width="30">2</td>, <td width="30">0</td>]
Теперь собираем строки в единую таблицу:
getTable(N, N) :- []; getTable(I, N) :- [<tr>_row(0, I, N);</tr> | getTable(I+1, N)];
Аргументы функция getTable(I, N):
I - счетчик строк N - размер матрицы
В этом определении строка формируется элементом
<tr>_row(0, I, N);</tr>
Осталось определить главную функцию, формирующую
html-документ в целом:
main(N) :- <html> <head><title>Диагональная матрица</title></head> <body> <h1>Матрица _N;x_N;</h1> <table>_getTable(0, N);</table> </body> </html>;
Можем строить матрицу:
?- writeHTML("matrix30.html", main(30), "w");
Результат - в файле matrix30.html.
|
/* приветствие */ greetings(Text) :- <html> <head><title>Приветствие</title></head> <body> <h1>_Text;</h1> </body> </html> ;
/* матрица */ row(N, M, N) :- []; row(M, M, N) :- !, [<td width="30">_M+1;</td> | row(M+1, M, N)]; row(I, M, N) :- [<td width="30">0</td> | row(I+1, M, N)];
getTable(N, N) :- []; getTable(I, N) :- [<tr>_row(0, I, N);</tr> | getTable(I+1, N)];
main(N) :- <html> <head><title>Диагональная матрица</title></head> <body> <h1>Матрица _N;x_N;</h1> <table>_getTable(0, N);</table> </body> </html>;
|
(1)?- load(xmlterms);
true
(2)?- greetings("Hello, World!");
<html> <head><title>Приветствие</title></head> <body> <h1>Hello, World!</h1> </body> </html>
(3)?- writeHTML("hello.html", greetings("Hello, World!"), "w");
true
(4)?- row(0, 1, 4);
[<td width="30">0</td>, <td width="30">2</td>, <td width="30">0</td>, <td width="30">0</td>]
(5)?- getTable(0, 3);
[<tr><td width="30">1</td><td width="30">0</td><td width="30">0</td> </tr>, <tr><td width="30">0</td><td width="30">2</td> <td width="30">0</td></tr>, <tr><td width="30">0</td> <td width="30">0</td><td width="30">3</td></tr>]
(6)?- main(3);
<html> <head><title>Диагональная матрица</title></head> <body> <h1>Матрица 3X3</h1><table><tr><td width="30">1</td> <td width="30">0</td><td width="30">0</td></tr> <tr><td width="30">0</td><td width="30">2</td><td width="30">0</td> </tr><tr><td width="30">0</td><td width="30">0</td> <td width="30">3</td></tr></table> </body> </html>
(7)?- writeHTML("matrix30.html", main(30), "w");
true
|