Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
43
Добавлен:
23.03.2015
Размер:
395.78 Кб
Скачать

4.2.1.Реализация на языке clu

Хотя, конечно, возможно реализовать типы на языках, ко­торые специально не приспособлены для этой цели, более удобно, если тип может быть реализован как отдельный программный модуль. Язык CLUпредоставляет такую программную единицу. Эта единица называетсякластер. (CLU,отметим, —это первые три буквы слова cluster.) Кластер включает в себя следующее.

1.Заголовок, в котором придаются имена реализуемому типу и операциям. Этот заголовок похож на заголовок в специфика­ции.

2.Определение представления, выбранного в данной реали­зации.

3.Реализации примитивных операций. Дополнительные про­граммы (процедуры и итераторы) также могут быть включены в кластер, но обращаться извне можно только к тем, которым приданы имена в заголовке.

Общий вид кластера представлен на рис. 4.4. dnarne = cluster is %список имен операцийre? =и здесь дается описание представления

%здесь помещаются реализации операций%если необходимо, здесь могут быть представлены%вспомогательные программы

end dnarne Рис. 4.4.Общий вид кластера.

Для представления наборов целых чисел с помощью массивов, например, мы указываем

гер = array tint ]

Эта строка выполняет две функции) информирует компиля­тор CLUо том, что в этом кластере представлением является мас­сив целых чисел и что в теле кластера обозначение герможет ис­пользоваться в качестве аббревиатуры для этого представленного массивом типа.

Внутри кластера должны быть доступны как абстрактный тип, так и тип представления. Более того, должна иметься воз­можность перехода от одного типа к другому. Например, опера­ция insertполучает в качестве аргумента набор целых чисел, но для реализации insertнеобходимо использовать массив, который представляет этот набор.

Возможность перехода от абстрактного типа к типу представ­ления и обратно в языке CLUобеспечивают ^две специальные операции: upи down.Операция upиспользует в качестве аргу­мента объект представления и в качестве результата выдает абстрактный объект, а операция downосуществляет обратное действие. Для того чтобы обеспечить преобразование абстрактного типа в тип представления и обратно, каждый кластер имеет свою собственную версию операций upи down.Эти операции автоматически определяются компилятором CLU.Например, в кластере процедуры intsetкомпилятор порождает операции up и downсо следующими заголовками:

up = proc (a: array tint 1) returns (intset) down == proc (s: intset) returns (array [int])

Операции upи downмогут использоваться только в кластерах и всегда осуществляют переход от абстрактного типа к типу пред­ставления и обратно только для кластера, в котором они появи­лись. Поэтому операции up и downне могут отрицательно по­влиять на контроль типов языка CLU.

Хотя операции upи downмогут появиться, где угодно, среди операций кластера, они в основном используются в одном из двух случаев. В первом случае, когда операция использует в ка­честве аргумента абстрактный объект, для преобразования этого объекта в тип представления используется операция down.Во вто­ром случае, когда операция возвращает заново созданный аб­страктный объект, сразу же перед возвратом для преобразования объекта представления в абстрактный тип используется операцияup.Для удобства работы язык CLUпредоставляет специально зарезервированное слово cvt.Слово cvtможет использоваться как тип аргумента или результата в заголовках операций кластеров. Использование его как типа аргумента указывает, что фактиче­ский аргумент —абстрактного типа, неформальный —типа пред­ставления и что поэтому к фактическому аргументу сразу же после вызова должна быть неявно применена операция down и результирующий объект представления должен быть присвоен формальному аргументу. Когда cvtиспользуется как тип резуль­тата, это означает, что результирующий объект —абстрактного типа, но возвращаемый объект—типа представления и что по­этому прямо перед возвратом к возвращаемому объекту неявно должна быть применена операция up.Слово cvtне добавляет ни­какой функциональности, которая не была бы обеспечена опера­циями upи down.Оно обеспечивает только удобство, которое возникает из возможности довольно просто описывать общие слу­чаи.

Теперь мы можем обратиться к представленной на рис. 4.5 реализации процедуры intset.

intset == cluster is create, insert, delete, member, size, choose rep = array [int]

create = proc ( ) returns (cvt) return (rep$new ( )) end create

insert = proc (s: intset, x: int)

if — member (s, x) then rep$addh (down (s), x) end end insert

delete = proc (s: cvt, x: int) j: int :== getind (s, x) if j <= rep$high (s) then s [j] := rep$top (s) % topвозвращает s [high (s)]

rep$remh (s) end end delete

member = proc (s: cvt, x: int) returns (bool) return (getind (s, x) <= rep$high (s)) end member

size ^ proc (s: cvt) returns (int^ return (rep$size (s)) end size

72Глава 4

choose = proc (s: cvt) returns (int)

return (rep$bottom (s)) % bottomвозвращает s [low (s) ] end choose

getind = proc (s: rep, x: int) returns (int) i: int : = rep$low (s) while i (== rep$high (s) do if x = s \i} then return (i) end i:=i+ I end return (i) end getind

end intset Рис. 4.5.Реализация типа данных intset.

Прежде всего обратим внимание на реализацию операцииcreate.Заголовок здесь следующий:

create = proc ( ) returns (cvt)

Следовательно, возвращается абстрактный объект, т. е. набор целых чисел. По оператору returnдолжен быть возвращен массив, но к этому объекту перед возвращением применяется операция up. Обратимся теперь к реализации операции insert.В этом слу-лае cvtне используется. Заголовок здесь следующий:

insert = proc (s: intset,х: int)

Следовательно, заданный пользователем абстрактный объект intsetне подвергается операции down.

Операция insertне возвращает никакого результата; вместо этого она модифицирует свой аргумент intset.В данной реализа­ции каждый элемент набора встречается в представляющем этот набор массиве только один раз; следовательно, операция insert не может просто добавить целое число х в массив. Она должна прежде проверить, не содержится ли уже х в массиве. Для этой цели используется операция member.Аргументом этой операции является набор целых чисел, поэтому в заголовке insertне ис­пользуется cvt.Заметим, что в обращении к операции member префикс «intset$»отсутствует; этот префикс не требуется, если операция вызывается внутри своего собственного кластера.

Если оказывается, что х не является членом s,к sявно при­меняется операция downи при помощи операции addhх добав­ляется в массив. Если х уже принадлежит s,массив не модифи­цируется. Заголовок операции deleteследующий:

delete = proc (s: cvt,х: int)

В этом случае к переданному в качестве аргумента абстракт­ному объекту intsetнемедленно применяется операция down и внутри операции delete sбудет иметь тип array [int].

Операция deleteдолжна прежде всего выяснить, принадле­жит ли х s.Для этого используется внутренняя процедура ge­tind.Если х есть в массиве, процедура getindвозвращает индекс, соответствующий расположению х, в противном случае возвра­щается число, большее верхней границы массива. Так как про­цедура getindне указана в заголовке кластера, она является вну­тренней для этого кластера, т. е. может быть вызвана только из этого кластера.

Если х принадлежит s,операция deleteпросто записывает верхний элемент массива в позицию х и затем уничтожает верх­ний элемент, используя операцию remh.При этом операция remh возвращает удаляемый элемент как результат, однако в нашем случае этот ненужный результат просто уничтожается.

Операция chooseпозволяет возвратить произвольный эле­мент s.Следовательно, при реализации этой операции мы можем действовать, как нам удобно. Один удобный выбор —это первый элемент массива, другой, тоже удобный, —последний элемент. Конечно, это приводит к тому, что операция chooseвозвращает обратившемуся к ней различные объекты, но, так как в специ­фикации chooseговорится, что выбор произвольный, не следует рассчитывать на возврат каких-то определенных объектов. От­метим, что в согласии со спецификацией операция chooseне из­меняет переданного ей в качестве аргумента набора intset.

Соседние файлы в папке POSIBNIK