- •1.Введение
- •1.1.Декомпозиция и абстракция
- •1.2.Абстракция
- •1.2.1.Абстракция через параметризацию
- •1.2.2.Абстракция через спецификацию
- •1.2.3.Виды абстракций
- •3.Процедурная абстракция
- •3.2.Спецификации
- •3.3.Спецификации процедурных абстракций
- •3.4.Реализация процедур
- •3.5.Более обобщенные процедуры
- •3.6.Создание процедурных абстракций
- •3.7.Заключение
- •4.Абстракции данных
- •4.1.Спецификации для абстракций данных
- •4.2.1.Реализация на языке clu
- •4.2.2.Замечания по поводу операций up и down
- •4.3.Использование абстракций данных
- •4.4.Реализация полиномов
- •4.5.Пояснения для понимания реализаций
- •4.5.1.Функция абстракции
- •4.5.2.Инвариант представления
- •4.6.3.Сохранение инварианта представления
- •4.5.4.Изменяемые представления
- •4.6.Параметризованные абстракции данных
- •4.7.Списки
- •4.8.Упорядоченные списки
3.2.Спецификации
Очень важно дать абстракциям четкие определения. В противном случае не могут быть достигнуты преимущества, рассмотренные в разд. 3.1.Например, мы можем заменить одну реализацию абстракции на другую только в том случае, если все то, что поддерживала старая реализация, поддерживает и новая. Элементом, создающим данную зависимость, является абстракция. Следовательно, мы должны знать, что она собой представляет.
Мы будем определять абстракции посредствомспецификаций, которые создаются наязыке спецификаций,причем последний может быть как формальным, так и неформальным. Преимущество формальных спецификаций заключается в том, что они имеют точно определенное значение. Неформальные спецификации легче читать и понимать, однако точное их содержание установить затруднительно, поскольку язык неформальных спецификаций точным не является. ^Несмотря на это, неформальные спецификации могут быть весьма информативны и составлены таким образом, что читатели без труда поймут их смысловое содержание. В нашей книге мы используем как формальные, так и неформальные спецификации, однако основной акцент делается на неформальных спецификациях. Формальные спецификации будут описаны в гл. 10.
Спецификация отлична от любой определяемой ей реализации абстракции. Все реализации сходны между собой, поскольку они реализуют одну и ту же абстракцию. Отличие их заключается в том, что это делается разными способами. Спецификация определяет их схожесть.
3.3.Спецификации процедурных абстракций
Спецификация процедуры состоит из заголовка и описания функции, выполняемого процедурой.Заголовоксодержит имя процедуры, номер, порядок и типы входных и выходных параметров. Кроме этого, выходные параметры могут, а входные должны быть поименованы. Например, заголовок для процедуры remove, dupis есть
remove_dupls == proc (a: array [int]) а заголовок для процедуры sqrtестьsqrt == proc (x: real) returns (rt: real)
Информация в заголовке чисто синтаксическая; она описывает «форму» процедуры. Это аналогично описанию «формы» математической функции:
Г: integer -> integer
Ни в одном из случаев смысл действий, выполняемых процедурой или функцией, не описывается. Эта информация приводится в семантической части спецификации, в которой смысл выполняемых процедурой действий описывается на естественном (разговорном) языке, возможно расширенном привычными математическими обозначениями. В этом описании используются имена входных и выходных параметров.
На рис. 3.2приводится шаблон спецификации для процедуры. Семантическая часть спецификации состоит из трех предложений — requires(требует), modifies(модифицирует) и effects(эффекты). Эти предложения должны появляться в указанном ниже порядке, однако предложения requiresи modifiesобязательными не являются.
рпагпе = proc (...) returns (..,)
requires %этот оператор задает необходимые требованияmodifies %этот оператор идентифицирует все модифицируемые входные
%данные
effects %этот оператор описывает выполняемые функции
Рис. 3.2.Шаблон спецификации для процедурных абстракций.
Предложение requiresзадает ограничения, накладываемые на абстракцию. Предложение requiresнеобходимо в том случае, если процедура является частичной, т. е. если ее поведение для некоторых входных значений недетерминировано. Если же процедура глобальна, т. е. ее поведение определено для всех входных значений, то предложение requiresможет быть опущено. В этом случае единственными требованиями, предъявляемыми при обращении к процедуре, являются требования, указанные в заголовке, т. е. число и типы аргументов. Оператор modifies задает список имен входных параметров, модифицируемых процедурой. Если входные параметры не указаны, то это предложение может быть опущено. Наконец, предложение effectsописывает работу процедуры со значениями, не охваченными предложением requires.Оно определяет выходные значения и модификации, производимые над входными параметрами, перечисленными в списке modifies.Предложение effectsсоставляется исходя из предположения, что требования предложения requiresудовлетворены. Однако в том случае, когда требования в предложении requiresне удовлетворены, о поведении процедуры ничего не сообщается.
concat = proc(а., Ь: string) returns (ab: string)
effectsпо возврату abесть новая строка, содержащая символы из а (в том порядке, в котором они расположены в а), за которыми следуют символы из b(в том порядке, в котором они расположены в Ь),remove_dupls = proc (a: array [int])
modifiesа
effectsУдаляет из массива а все повторяющиеся элементы. Нижняя гра^ ница а остается без изменений, однако порядок следования оставшихся элементов может измениться. Если, например, перед вызовом а == [1: 3, 13, 3, 6],то по возвращению массив а имеет нижнюю границу, равную 1,и содержит три элемента 3, 13и 6,расположенных в некоторой неопределенной последовательности.search == proc(a: array [int],х: int) retunis (i; int) requiresмассив а упорядочен по возрастанию.
effectsЕсли элемент х принадлежит массиву а, то возвращается значение iтакое, что а [i ] =х; в противном случае значение iна единицу больше, чем значение верхней границы массива а.
Рис. 3.3.Спецификация процедурной абстракции.
На рис. 3.3приведено несколько спецификаций. Процедураconcatне модифицирует входные переменные, а процедура ге-move_duplsизменяет входной массив, что отмечено в предложении modifies.Отметим, что в спецификации процедуры remove. dupisдается пример. Наличие примеров облегчает понимание спецификации, и их рекомендуется использовать во всех подходящих случаях.
Процедуры concatи remove_duplsявляются общими процедурами, поскольку их спецификации не содержат предложенийrequires.Процедура searchявляется частичной; она выполняет свои функции только в том случае, если входной массив отсортирован. Отметим, что предложение effectsничего не говорит о результате работы процедуры в том случае, когда входной массив не отсортирован. В этом случае составитель процедуры может выбрать любой подходящий для него вариант; например, процедура searchможет в этом случае возвращать индекс, выходящий за границы массива, или индекс, лежащий в пределах границ, но не содержащий х, или даже зацикливаться.
Спецификации составляются на языке спецификаций, а не на языке программирования. Следовательно, рассмотренные ранее спецификации написаны не на языке CLU.Кроме этого, спецификации обычно принципиально отличаются от программ, поскольку они фокусируют свое внимание на описании самой абстракции, а не ее реализации. Мы вернемся к описанию спецификаций.