Исключения развивались как обобщение ошибок. Первый язык программирования , чтобы включить механизм исключения был Lisp в начале 1970 - х годов. В книге «Паттерн эволюции языка » есть хорошее резюме Габриэля и Стила., Исключения (которые еще не назывались исключениями) возникли из-за необходимости указывать поведение программы в случае возникновения ошибки. Одна возможность - остановить программу, но это не всегда полезно. В реализациях Lisp традиционно был способ войти в отладчик при ошибке, но иногда программисты хотели включить обработку ошибок в свою программу. Таким образом, в реализациях Lisp 1960-х годов был способ сказать: «сделай это, и если произойдет ошибка, сделай это вместо этого». Первоначально ошибки исходили из примитивных функций, но программисты сочли удобным преднамеренно вызвать ошибку, чтобы пропустить некоторую часть программы и перейти к обработчику ошибок.
В 1972 году современная форма обработки исключений в Lisp появилась в MacLisp: throw
и catch
. Группа по сохранению программного обеспечения перечисляет много материалов о ранних реализациях Lisp, включая Редакцию 0 Справочного руководства MACLISP Дэвида Муна . Примитивы catch
и throw
документированы в §5.3 с.43.
catch
является функцией LISP для выполнения структурированных нелокальных выходов (catch x)
оценивает x
и возвращает его значения, за исключением того, что если во время оценки x
(throw y)
следует оценивать, catch
немедленно возвращается y
без дальнейшей оценки x
.
catch
может также использоваться со вторым аргументом, не оцененным, который используется в качестве тега для различения вложенных уловов. (...)
throw
используется catch
в качестве структурированного нелокального механизма выхода.
(throw x)
оценивает x
и выбрасывает значение обратно к самому последнему catch
.
(throw x <tag>)
бросает значение x
назад в самое последнее, catch
помеченное <tag>
или немаркированное.
Основное внимание уделяется нелокальному управлению потоком. Это форма goto (goto-only goto), которая также называется прыжком . Метафора заключается в том, что одна часть программы выдает значение для возврата в обработчик исключений, а обработчик исключений перехватывает это значение и возвращает его.
Большинство языков программирования сегодня упаковывают тег и значение в объект исключения и комбинируют механизм перехвата с механизмом обработки.
Исключения не обязательно являются ошибками. Это способ выхода из блока кода и из окружающих блоков, экранирование до тех пор, пока не будет достигнут обработчик для исключения. Считается ли такая вещь «ошибкой» в интуитивном смысле, субъективно.
В некоторых языках проводится различие между терминами «ошибка» и «исключение». Например, некоторые диалекты Lisp должны как throw
вызывать исключение (поток управления для пользователей, предназначенный для выполнения нелокального выхода, который не указывает, что что-то пошло не так), так и signal
выдавать ошибку (которая указывает, что что-то пошло не так и может вызвать событие отладки).