- •1. Теория направленных отношений.
- •1.1. Основные понятия.
- •2.2. Языки и схемы направленных отношений.
- •2. Сетевое представление направленных отношений.
- •2.1. Формальное определение сетевого представления НО.
- •2.2. Графическая интерпретация сетевого представления.
- •2.3. Вычисление НО на основе КССГ.
- •2.4. Стратегии вычисления НО.
- •3.2. Синтаксис языка и семантика S-FLOGOL.
- •4.1. Базовые средства языка.
- •4.2. Средства схемной надстройки языка S-FLOGOL.
- •4.3. Системные отношения.
- •5. Интегрированная среда разработки программ.
- •5.1. Центральный модуль.
- •5.2. Текстовый редактор.
- •5.3. Графический редактор.
- •5.4. Вычисление запроса.
- •5.5. Отладка программ.
- •Список литературы
Помимо возможности более удобного в некоторых случаях описания отношений, применение композиционного стиля программирования позволяет полностью отказаться от использования графиков отношений и, соответственно, индивидных переменных, что сближает такой стиль программирования с идеями комбинаторной логики.
4.2. Средства схемной надстройки языка S-FLOGOL.
Во второй части нашего описания методов программирования на языке S-FLOGOL мы рассмотрим вопросы использования метасредств, или, по-другому, схемной надстройки языка, к которой относятся индексация, параметризация, свертка и условная конструкция IF.
Параметризация позволяет использовать в определении отношения отношения-параметры, которые задаются в месте вызова определяемого
отношения. Вызов параметров осуществляется по номеру, который они получают в точке вызова при вычислении выражения, определяющего список фактических параметров.
Фактические параметры вызова указываются в квадратных скобках после имени вызываемого отношения в схемах вызова (в первичных выражениях реляционного выражения, терма, и формулы). В качестве фактических параметров вызова используются имена отношений, возможно, также параметризованных. Таким образом, каждый параметр может представлять собой древовидную структуру параметризованных вызовов.
R
P K
S T
Например, параметр R[P[S;T];K] может быть представлен деревом следующего вида:
В кружках размещены имена отношений, связь с параметрами вызова
которых отражается дугами. В общем случае, такая структура может иметь
неограниченную вложенность.
Напомним, что использование параметров вызова при определении отношения осуществляется указанием в уголковых кавычках номера
32
параметра вместо имени вызываемого отношения. Номер параметра задается арифметическим выражением и определяет отношение, имя которого располагается под указанным номером в списке параметров (нумерация элементов списка начинается с нуля).
Приведем примеры использования параметризации. В качестве первого примера определим отношение, организующее вызов отношенияпараметра с подачей на его вход двух аргументов, вычисленных также переданными в качестве параметров отношениями:.
ApplyRel = (<<1>>#<<2>>)•<<0>>
Тогда запрос к отношению из приведенного выше примера может быть записан как:
QUERY = ApplyRel[Append;List1;List2],
В результате подстановки параметров (в процессе компиляции) запрос приобретет следующий вид:
QUERY = (List1# List2)•Append.
В качестве второго примера приведем отношение Map, применяющее переданное отношение-параметр ко всем элементам списка.
Map={Nil : Nil} {Cons(x,xs) : Cons(<<0>>(x),@(xs)}
Для инкрементации элементов списка можно использовать следующий вызов:
IncList = Map[Succ](List1),
что эквивалентно вызову отношения IncList, определенного правилом вида:
IncList={Nil : Nil} {Cons(x,xs):Cons(Succ (x),@(xs)}.
Транзитная передача полного списка параметров может быть продемонстрирована следующим примером (передача параметров вызова
отношения R в вызовы отношений R1 и R2):
R = R1[@]•R2[@].
Имена отношений и переменных термов могут быть индексированы.
Наиболее интересно применение списка индексов для объектов,
находящихся в области действия переменной свертки, поскольку
арифметическое выражение может использовать текущее значение переменной свертки, что позволяет давать объекту имя, зависимое от значения одной или сразу нескольких переменных свертки.
33
В качестве простого примера покажем использование индексации для именования натуральных чисел:
[2]Nat = Null•Succ•Succ;
[3]Nat= [2]Nat•Succ;
QUERY = ([2]Nat#[3]Nat)•Add.
Свертка включается во все выражения языка S-FLOGOL и позволяет в компактной форме описывать множество объектов, определяемых общим выражением с различными значениями переменной свертки. В качестве примера применения свертки покажем определение натуральных чисел при помощи свертки по операции последовательной композиции в реляционном выражении:
[10]Nat = Null•(•I=1..10)Succ.
Используя свертку по доменному выражению, можно определять сразу множество отношений. Например, множество натуральных чисел (ограниченное сверху числом 100) можно определить при помощи сверток по доменному и реляционному выражению:
(I=1..100)[I]Nat = Null•(•J=1..I)Succ.
Поскольку для доменного выражения определена только одна инфиксная операция объединения (‘;’), то в свертке она не указывается.
Другим удобным применением является использование сверток для формирования термов:
FC = {C((,I=0..>C)[I]x : F((,I=0..>C)[I]x)}.
В примере показано применение функции F к объектам, полученным применением конструктора C. Заметим, что количество входов конструктора здесь жестко не задано и получается при помощи арифметического выражения >C. Например, если конструктор C имеет 3 входа, то это
определение эквивалентно следующему определению:
FC = {C([1]x,[2]x,[3]x) : F([1]x,[2]x,[3]x)}.
Условная конструкция IF также включается в средства конструирования выражений всех типов. В качестве примера использования
условной конструкции покажем определение натурального числа одной лишь
сверткой без дополнительной композиции с конструктором Null:
[10]Nat = (•I=1..10) IF I=0 THEN Null ELSE Succ.
34
На этом завершим рассмотрение схемной надстройки языка S- FLOGOL и перейдем к рассмотрению построения многомодульных программ. В качестве примера многомодульной программы приведем программу, использующую модуль определения натуральных чисел и арифметических операций над ними, а также модуль работы со списками.
MODULE Arithm (0:1)Null; (1:1)Succ;
(I=1..100) [I]Nat = Null•(•J=1..I)Succ; Add = {Null,x : x};
Add = {Succ(x),y : Succ(@(x,y))}; Mult = {Null,x : Null};
Mult = {Succ(x),y : Add(@(x,y),y)}
…
END MODULE Lists
(0:1)Nil; (1:1)Cons;
//Отношение формирования списка; (I=1..100)
[I]List=IF I>0 THEN ({:Nil}• (•J=0..I-1){x: y? Cons(«(I-J-1)»,x)=y}) ELSE Nil;
//Сцепление списков;
Append = {Nil,x: x};
Append = {Cons(x,xs),ys : Cons(x, @(xs,ys))}
…
END
MODULE SomeOne(Arithm,Lists)
List1 = [3]List[[5]Nat;[2]Nat;[3]Nat]; List2 = [2]List[[12]Nat;[7]Nat];
QUERY = (List1#List2)•Append
END
35
