29.1 Введение

Обычно мы описываем функции, как если они работают в «обычной ситуации». Например, мы может сказать, что функция + возвращает сумму аргументов, или что read-char возвращает доступный символ из входного потока.

Однако, иногда возникают «исключительные ситуации», которые в такие описания не вписываются. Например, + может получить аргумент, который не является числом, или read-char может получить аргумент — поток, в котором не осталось данных. Это разграничение между обычной и исключительной ситуациями в некотором смысле непостоянно, но на практике оно очень полезно.

Например, предположим, функция f была определена только для целочисленных аргументов, но также гарантированно определяет некорректные аргументы и сигнализирует в этом случае ошибку. Фактически, такое описания противоречиво, так как поведение функции для нечисловых аргументов хорошо и ясно определено. Однако мы бы не хотели избегая парадокса строить описание как, например, функция f принимает все виды аргументов (даже если при этом она сигнализирует ошибку). Используя разграничение нормальная/исключительная ситуации, мы можем чётко сказать, что f в нормальной ситуации принимает целочисленные аргументы и сигнализирует ошибку в исключительной. Более того, мы можем сказать, что когда мы неформально ссылаемся на определение функции, мы имеем ввиду её поведение в нормальной ситуации. Например, мы можем неформально сказать о f, как о функции, которая принимает только целочисленные аргументы, и не почувствуем каких-либо угрызений совести. FIXME

Не все исключительные ситуации являются ошибками. Например, программа, которая выводит длинную строку текста может придти к концу-строки (end-of-line). Вполне возможно, что никакого реального вреда от конца строки нет и сигнал об ошибке не несёт критического смысла, поскольку операционная система просто переведёт курсор на следующую строку и вывод строки может продолжаться. Однако, это может быть интересно спроектировать протокол, где программы вывода может информировать вызвавшего её о исключениях типа конец-строки. Вызывающей код в этом случае должен будет в этой ситуации в это же время принять решение о дальнейших действия. Например, вызывающий код может выбрать действие о завершении вывода, продолжении без символа конца-строки. Однако, важная вещь в том, что отказ вызывающего кода в предоставлении совета насчёт исключительной ситуации не мешает выводящей программе работать правильно.

Механизмы для обработки исключительных ситуаций отличаются друг от друга. При возникновении исключительной ситуации, программа может попытаться справиться с ней с помощью возврата исключительного значения, возвращения дополнительного значения, установки переменной-флага, вызова функции, выполнения специальной передачи управления, или остановки программы или в целом, или с переходом в отладчик.

По большей части, средства, описанные в этой главе не вводят каких-либо принципиально новых способов борьбы с исключительными ситуациями. Они, скорее, включают и формализуют полезные модели данный и управления потоком выполнения, которые могут использоваться для обработки исключительных ситуаций.

Необходимый концептуальный подхода обработки ошибок, возможно, следует начать с первого принципа, с обсуждения условий в целом, и в конечном итоге придти к понятию ошибки, как одному из видов условий. Однако, учитывая простейшее устройство технологии обработки ошибок, объяснение механизма в целом столь же неуместно, как, например, требование к нищему сначала научится готовить изысканное блюдо, прежде чем поесть. Таким образом, мы сначала рассмотрим необходимое — обработку ошибок, а затем — вернёмся и заполним недостающие подробности описанием всей системы.