Исключения развивались как обобщение ошибок. Первый язык программирования , чтобы включить механизм исключения был 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выдавать ошибку (которая указывает, что что-то пошло не так и может вызвать событие отладки).