As exceções evoluíram como uma generalização de erros. A primeira linguagem de programação a incluir um mecanismo de exceção foi o Lisp no início dos anos 70. Há um bom resumo em A Pattern of Language Evolution, de Gabriel e Steele. Exceções (que ainda não foram chamadas de exceções) surgiram da necessidade de especificar o comportamento de um programa se ocorrer um erro. Uma possibilidade é interromper o programa, mas isso nem sempre é útil. As implementações do Lisp tradicionalmente tinham uma maneira de inserir o depurador em um erro, mas às vezes os programadores queriam incluir a manipulação de erros em seu programa. Portanto, as implementações do Lisp dos anos 60 tinham uma maneira de dizer "faça isso, e se ocorrer um erro, faça isso". Originalmente, os erros vinham de funções primitivas, mas os programadores acharam conveniente acionar deliberadamente um erro para pular parte do programa e pular para o manipulador de erros.
Em 1972, a forma moderna de tratamento de exceções no Lisp apareceu no MacLisp: throw
e catch
. O Grupo de Preservação de Software lista muito material das implementações iniciais do Lisp, incluindo The MACLISP Reference Manual Revision 0, de David Moon . As primitivas catch
e throw
estão documentadas em §5.3 p.43.
catch
é a função LISP para executar saídas não locais estruturadas. (catch x)
avalia x
e retorna seus valores, exceto que, se durante a avaliação de x
(throw y)
deve ser avaliado, catch
retorna imediatamente y
sem avaliação adicional x
.
catch
também pode ser usado com um argumento econd, não avaliado, que é usado como uma marca para distinguir entre capturas aninhadas. (…)
throw
é usado catch
como um mecanismo de saída não-local estruturado.
(throw x)
avalia x
e lança o valor de volta ao mais recente catch
.
(throw x <tag>)
lança o valor de x
volta para o mais recente catch
rotulado com <tag>
ou sem rótulo .
O foco está no fluxo de controle não - local . É uma forma de goto (apenas para cima), que também é chamada de salto . A metáfora é que uma parte do programa lança o valor para retornar ao manipulador de exceções, e o manipulador de exceções captura esse valor e o retorna.
Atualmente, a maioria das linguagens de programação compacta a tag e o valor em um objeto de exceção e combina o mecanismo de captura com um mecanismo de manipulação.
Exceções não são necessariamente erros. Eles são uma maneira de sair de um bloco de código e dos blocos circundantes, escapando até que um manipulador da exceção seja atingido. Se uma coisa dessas é considerada um "erro" no sentido intuitivo é subjetivo.
Alguns idiomas fazem uma distinção entre os termos "erro" e "exceção". Por exemplo, alguns dialetos Lisp têm throw
que gerar uma exceção (fluxo de controle para usuários, destinado a executar uma saída não local de uma maneira que não indique que algo deu errado)) e signal
gerar um erro (que indica que algo deu "errado" e pode desencadear um evento de depuração).