- •4.9.1. Изменяемость
- •4.9.2. Классы операций
- •98 Глава 4
- •4.9.3. Полнота
- •100 Глава 4
- •4.9.5. Операции egual, similar и copy
- •102 Глава 4
- •104 Глава 4
- •5. Исключительные ситуации
- •108 Глава 5
- •110 Глава 5
- •6.2.1. Сигнализация об исключительных ситуациях
- •5.2.2. Обработка исключительных ситуаций
- •112 Глава 5
- •5.2.3. Предложение resignal
- •6.2.4. Необрабатываемые исключительные ситуации
- •114 Глава 5
- •6.2.3. Предложение resignal
- •5.2.4. Необрабатываемые исключительные ситуации
- •116 Глава 5
- •118 Глава 5
- •118 Глава 5
- •120 Глава 5
- •122 Глава 5
- •124 Глава 5
- •128 Глава 6
- •130 Глава 6
- •6.2.1. Реализация итераторов
- •6.2.2. Использование итераторов
- •132 Глава 6
- •134 Глава 6
- •136 Глава 6
- •138 Глава 6
- •140 Глава 7
- •142 Глава 7
- •7.2. Абстракция данных
- •144 Глава 7
- •146 Глава 7
- •148 Глава 7
- •150 Глава 7
- •7.4. Генераторы
- •162 Глава 7
- •154 Глава 7
- •156 Глава 7
- •162 Глава 8
- •164 Глава 8
- •166 Глава 8
- •168 Глава 8
- •170 Глава 9
- •172 Глава 9
- •174 Глава 9
- •176 Глава 9
- •9.1.3. Пример
- •178 Глава 9
- •180 Глава 9
- •182 Глава 9
- •184 Глава 9
- •186 Глава 9
- •188 Глава 9
- •190 Глава 9
- •192 Глава. 9
- •194 Глава 9
142 Глава 7
(Мы используем знак плюс для обозначения конкатенации строк. Эта операция обозначается одинаково в версиях языка Паскаль, которые поддерживают строки.) К процедуре failure обращаются тогда, когда в языке CLU явно или неявно будет сигнализировано состояние сбоя failure. Аргумент при обращении должен, конечно, идентифицировать проблему и операцию, в которой она произошла. Обычно тип error.msg будет объявляться как некоторый тип строк. Если в используемом языке Паскаль строки не поддерживаются, аргумент может быть представлен как упакованный массив символов.
search ==ргос^а: int_array, х: int) returns (i: int)
signals (not- in)
effects Если переменная х находится в массиве а, то возвращается такой индекс i, что а [i] == х, в противном случае сигнализируется состояние not- in.
Эта спецификация иллюстрирует использование в языке CLU обработки исключительной ситуации, не связанной со сбоем. В языке Паскаль мы достигаем аналогичного эффекта при помощи следующей конструкции:
function searchi (var a: int. array; х: integer; var i: integer):
search I - exceptions modifies i
effects Если переменная х находится в массиве а, то индекс i устанавливается таким, что а [i] =; х, и возвращается значение ok; в противном случае возвращается значение not-in.
где searchl-exceptions является вычисляемым типом type searchLexceptions == (ok, not-in)
Отметим, что функция searchi имеет третий аргумент — параметр i с типом var. Эта переменная используется для получения результата в нормальном случае.
По соглашению все обращения к этой функции мы вставляем в предложение case следующим образом:
case searchi (а, х, i) of ok:a[i):=a[i]+l; not-in: write («Элемент не найден») end
Предложение case должно иметь ветвь, соответствующую каждому значению, которое может быть возвращено функцией. (Если возможны только две альтернативы, как в случае с функцией searchi, результат мор бы иметь булевский тип, а не вычисляемый тип, и оператор if мог бы использоваться вместо предложения case.)
Этот подход имеет несколько недостатков. Неудобно, что функция searchi модифицирует параметр с типом var вместо выдачи
Использование языка Паскаль
индекса, поскольку мы не сможем тогда ее использовать в таких выражениях, как a [search I (a, x)L Более того, функция searchi не так надежна при использовании, как процедура search. Например, предположим, что мы решили добавить еще одно значение в тип searchi-exceptions. В соответствии с нашими соглашениями надо добавить еще одну ветвь к каждому предложению case, в котором имеется обращение к функции searchi. Если, однако, это не будет сделано, то не возникнет ни ошибки во время компиляции, ни ошибок во время счета. (В языке Паскаль, если переключатель в предложении case не соответствует никакой из ветвей, программа продолжает выполнение g предложения, следующего за предложением case.)
7.2. Абстракция данных
В этом разделе мы опишем некоторый подход для спецификации, использования и реализации абстракций данных при программировании на языке Паскаль. Этот подход основывается сугубо на соглашениях по программированию. В языке CLU, наоборот, — компилятор обеспечивает непосредственную поддержку этих абстракций. Данные соглашения разработаны в основном для того, чтобы показать, что мы можем реализовать абстракции данных, не разрабатывая повторно какие-либо модули, которые их используют, и что можем возвращать из функций абстрактные значения.
На рис. 7.1 показана спецификация абстракции данных для очереди целых чисел. В этой абстракции задается тип intqueue и набор операций, которые по соглашению допускаются для работы с представлением этого типа. Имена всех операций начинаются с префикса q. Будем следовать этому соглашению, чтобы избежать конфликтов с именами операций, используемых для других типов данных.
Отметим, что, несмотря на тот факт, что обе операции q-ap-pend и q-remfirst формально модифицируют очередь q, сама очередь q не передается, как некоторый тип var. Мы реализуем тип данных intqueue и другие абстрактные типы, используя указатели на неупорядоченный массив. Когда мы передаем в процедуру некоторый абстрактный объект, то, следовательно всегда передаем некоторую ссылку. Чтобы модифицировать абстрактный объект, модифицируем тот объект, на который указывает ссылка, а не саму ссылку. Таким образом, абстрактные объекты никогда не передаются, как параметры типа var.
Наше решение хранить абстрактные объекты в неупорядоченном массиве продиктовано тем, что надо реализовать типы, чьи объекты изменяют свой размер по мере работы программы. Мы настаиваем на том, чтобы представление было некоторой ссыл».
