- •4.9.1. Изменяемость
- •4.9.2. Классы операций
- •4.9.3. Полнота
- •4.9.5. Операции egual, similar и copy
- •5. Исключительные ситуации
- •6.2.1. Сигнализация об исключительных ситуациях
- •5.2.2. Обработка исключительных ситуаций
- •5.2.3. Предложение resignal
- •6.2.4. Необрабатываемые исключительные ситуации
- •6.2.3. Предложение resignal
- •5.2.4. Необрабатываемые исключительные ситуации
- •6.2.1. Реализация итераторов
- •6.2.2. Использование итераторов
- •7.2. Абстракция данных
- •7.4. Генераторы
- •9.1.3. Пример
6.2.1. Сигнализация об исключительных ситуациях
Процедура, написанная на языке CLU, может завершить работу по одному из некоторого количества условий. В ее заго^ ловок включены имена исключительных ситуаций и определены число и типы результатов, возвращаемых в каждом случае. Например, имеем заголовок
choose = proc (s: intset) returns (int) signals (empty) search = proc (a: array [int], х: int) returns (int)
signals (not_in, duplicate (int))
При «обычном» завершении работы этой процедуры она выходит либо на конец своего тела программы, либо на оператор return. Для завершения работы с исключительной ситуацией «имя» процедура использует предложение signal
signal имя (выражение)
Предложение signal верно, только если имя исключительной ситуации указано в заголовке процедуры (или есть failure, что рассматривается в разд. 5.2.4). На рис. 5.2 представлена иллюстрирующая сигнализацию реализация процедуры choose. Здесь мы предполагаем, что используется реализация intset, представленная на рис. 4.5.
rep = array [inf ]
choose == proc (s: cvt) returns (int) signals (empty) if rep$size (s) •= 0 then signal empty end return (rep$bottom (s)) end choose
Рис. 5.2. Реализация процедуры choose.
5.2.2. Обработка исключительных ситуаций
При завершении работы процедуры с исключительной ситуацией, вызывающая программа должна иметь возможность передать управление программе, которая будет обрабатывать эту исключительную ситуацию. Для этой цели в языке CLU имеется предложение except, которое имеет следующий вид:
Предложение except список программ обработки end
Список программ обработки исключительных ситуаций включает в себя некоторое подмножество (возможно, и все множество) исключительных ситуаций. Каждая программа обработки из списка содержит имена одной или нескольких исключительных ситуаций, за которыми следует список операторов тела программы обработки, определяющих действия, которые должны быть совершены в случае возникновения этих исключительных
112 Глава 5
ситуаций. Разрешение иметь несколько имен исключительных ситуаций для одной и тЬй же программы обработки позволяет избежать дубликатов программ в случаях, когда несколько исключительных ситуаций обрабатываются одинаково.
Когда возникает исключительная ситуация, программа прекращает свое обычное выполнение и управление передается ближайшему предложению except с программой обработки, имеющей имя этой исключительной ситуации. Например, если вызов процедуры intset$choose в предложении
i: = intset$choose (s)
заканчивается с исключительной ситуацией empty, присвоение значения переменной i не делается и управление передается ближайшему предложению except с программой обработки для empty.
Имеется несколько различных форм программ обработки, использование которых связано с тем, имеют ли поименованные исключительные ситуации связанные с ними результирующие объекты и используются ли эти объекты в теле программы обработки. Для обработки одной или нескольких исключительных ситуаций, с которыми не связаны объекты, мы просто перечисляем имена исключительных ситуаций. Например, оператор
when overflow, zero_ divide: тело
будет обрабатывать исключительные ситуации с именами overflow и zero-divide, ни одна из которых не имеет никаких связанных с ней результирующих объектов. Тело программы обработки следует за zero-divide. Например,
z :== х/у except when overflow, zero-divide : z := 0 end
Для обработки прерываний с результирующими объектами, которые используются в теле программы обработки, имена должны быть связаны с объектами. Снова дается список имен, но вслед за ним идут описания локальных переменных, являющихся именами результирующих объектов. Например,
when duplicate (j: int): тело
Область действия описаний — тело программы обработки. Все поименованные исключительные ситуации должны возвращать объекты указанных типов в указанном порядке. При выполнении программы обработки эти объекты присваиваются локальным переменным и затем выполняются операторы тела. Например, если процедура search (а, х) сигнализирует об исключительной ситуации duplicate, то после выполнения операторов
х := search (а, х) except when duplicate (j: int): i :== j end
Исключительные ситуации
i будет содержать индекс, соответствующий расположению х в а. Для обработки исключительных ситуаций с результирующими объектами, которые не используются в теле программы обработки, вслед за списком имен ставится (*). Например,
when noLin, duplicate (*): тело.
Нет необходимости согласовывать число и типы результирующих объектов, связанных с исключительной ситуацией, заданной в такой форме. Например, исключительная ситуация duplicate имеет один результирующий объект, a not-in не имеет ни одного. Используя эту форму, можно составить программу так, что при возникновении исключительной ситуации процедура будет возвращать всю возможно полезную информацию; если же вызывающей программе эта информация не требуется, она может игнорировать ее.
Если программист хочет обрабатывать все остальные исключительные ситуации, не перечисляя их имен, в предложении except в качестве последней программы обработки может быть использована одна из следующих форм. Форма
others: тело
используется в случае, когда информация об именах исключительных ситуаций и результирующих объектах не важна. Если желательна информация об имени исключительной ситуации, то используется форма
others (name: string): тело.
Здесь имя исключительной ситуации дается телу программы обработки как строка.
Заметим, что в программе обработки others все результаты исключительной ситуации теряются. Программа обработки others используется для стандартной чистки после различных исключительных ситуаций, результаты которых не важны. Примером может служить программа, которая должна перед возвратом закрывать поток независимо от возникшей проблемы.
Предложения except могут быть вложенными. Предложение except как целое может внутри самого себя вызвать любые исключительные ситуации, которые не включены в его список программ обработки, плюс любые исключительные ситуации, которые вызывает список программ обработки. На рис. 5.3 даны примеры использования предложения except.
Процедура index_sum пытается получить сумму индексов массива а, в котором хранятся элементы набора целых чисел s; если встречаются затруднения, процедура сигнализирует об исключительной ситуации problem. На рисунке возможные сигналы показаны как комментарии к каждому предложению. Для того чтобы
Л4 Глава 5
index _sum == proc (s: intset, a; array [int]) returns (int) signals (problem) sum: int := 0 while true do
x: int •.= intset$choose (s) % может сигнализировать о пустом наборе sum :== surn + search (a, x) % overflow, not_in и duplicate
except when duplicate (j: int): sum := sum + j end % overflow intset$delete (s, x) end except when empty: return (sum)
others: signal problem end end index.sum
Рис. 5.3. Примеры предложений except.
закончить цикл, используется исключительная ситуация empty, которая может возникнуть при вызове choose. Исключительная ситуация duplicate, которая может возникнуть при вызове search, обрабатывается во вложенном предложении except, а исключительная ситуация not_ in — во внешнем except, в ветви others. В этой ветви обрабатывается также и overflow.