Erlang - Exceções

O tratamento de exceções é necessário em qualquer linguagem de programação para tratar os erros de tempo de execução de forma que o fluxo normal do aplicativo possa ser mantido. A exceção normalmente interrompe o fluxo normal do aplicativo, razão pela qual precisamos usar o tratamento de exceções em nosso aplicativo.

Normalmente, quando ocorre uma exceção ou erro em Erlang, a seguinte mensagem será exibida.

{"init terminating in do_boot", {undef,[{helloworld,start,[],[]}, 
{init,start_it,1,[]},{init,start_em,1,[]}]}}

Crash dump será gravado em -

erl_crash.dump
init terminating in do_boot ()

Em Erlang, existem 3 tipos de exceções -

  • Error - Ligando erlang:error(Reason)encerrará a execução no processo atual e incluirá um rastreamento de pilha das últimas funções chamadas com seus argumentos quando você o capturar. Esses são os tipos de exceções que provocam os erros de tempo de execução acima.

  • Exists- Existem dois tipos de saídas: saídas 'internas' e saídas 'externas'. As saídas internas são acionadas chamando a funçãoexit/1e fazer com que o processo atual interrompa sua execução. As saídas externas são chamadas comexit/2 e tem a ver com vários processos no aspecto simultâneo de Erlang.

  • Throw- Um lançamento é uma classe de exceção usada para casos que se espera que o programador trate. Em comparação com saídas e erros, eles não trazem nenhum 'travamento desse processo!' intenção por trás deles, mas ao invés disso, eles controlam o fluxo. Conforme você usa throws enquanto espera que o programador os controle, geralmente é uma boa ideia documentar seu uso dentro de um módulo que os usa.

UMA try ... catch é uma forma de avaliar uma expressão enquanto permite lidar com o caso de sucesso e também com os erros encontrados.

A sintaxe geral de uma expressão try catch é a seguinte.

Sintaxe

try Expression of 
SuccessfulPattern1 [Guards] -> 
Expression1; 
SuccessfulPattern2 [Guards] -> 
Expression2 

catch 
TypeOfError:ExceptionPattern1 -> 
Expression3; 
TypeOfError:ExceptionPattern2 -> 
Expression4 
end

A expressão entre try and ofé dito ser protegido. Isso significa que qualquer tipo de exceção que aconteça nessa chamada será detectada. Os padrões e expressões entre ostry ... of and catch se comportar exatamente da mesma maneira que um case ... of.

Finalmente, a parte catch - aqui, você pode substituir TypeOfErrorpor erro, lançamento ou saída, para cada tipo respectivo que vimos neste capítulo. Se nenhum tipo for fornecido, um lançamento é assumido.

A seguir estão alguns dos erros e os motivos dos erros em Erlang -

Erro Tipo de Erro
badarg Argumento ruim. O argumento tem tipo de dados incorreto ou está mal formado.
Badarith Argumento ruim em uma expressão aritmética.
{badmatch, V} A avaliação de uma expressão de correspondência falhou. O valor V não correspondeu.
function_clause Nenhuma cláusula de função correspondente é encontrada ao avaliar uma chamada de função.
{case_clause, V} Nenhuma ramificação correspondente foi encontrada ao avaliar uma expressão case. O valor V não correspondeu.
oração condicional Nenhuma ramificação verdadeira é encontrada ao avaliar uma expressão if.
{try_clause, V} Nenhuma ramificação correspondente foi encontrada ao avaliar a seção de uma expressão try. O valor V não correspondeu.
undef A função não pode ser encontrada ao avaliar uma chamada de função.
{badfun, F} Algo está errado com um divertido F
{badarity, F} Uma diversão é aplicada ao número errado de argumentos. F descreve a diversão e os argumentos.
timeout_value O valor de tempo limite em uma expressão receive..after é avaliado como algo diferente de um inteiro ou infinito.
noproc Tentando vincular a um processo não existente.

A seguir está um exemplo de como essas exceções podem ser usadas e como as coisas são feitas.

  • A primeira função gera todos os tipos possíveis de uma exceção.

  • Em seguida, escrevemos uma função de wrapper para chamar generate_exception em uma expressão try ... catch.

Exemplo

-module(helloworld). 
-compile(export_all). 

generate_exception(1) -> a; 
generate_exception(2) -> throw(a); 
generate_exception(3) -> exit(a); 
generate_exception(4) -> {'EXIT', a}; 
generate_exception(5) -> erlang:error(a). 

demo1() -> 
   [catcher(I) || I <- [1,2,3,4,5]]. 
catcher(N) -> 
   try generate_exception(N) of 
      Val -> {N, normal, Val} 
   catch 
      throw:X -> {N, caught, thrown, X}; 
      exit:X -> {N, caught, exited, X}; 
      error:X -> {N, caught, error, X} 
   end. 
      
demo2() -> 
   [{I, (catch generate_exception(I))} || I <- [1,2,3,4,5]]. 
demo3() -> 
   try generate_exception(5) 
   catch 
      error:X -> 
         {X, erlang:get_stacktrace()} 
   end. 
   
lookup(N) -> 
   case(N) of 
      1 -> {'EXIT', a}; 
      2 -> exit(a) 
   end.

Se executarmos o programa como helloworld: demo (). , obteremos a seguinte saída -

Resultado

[{1,normal,a},
{2,caught,thrown,a},
{3,caught,exited,a},
{4,normal,{'EXIT',a}},
{5,caught,error,a}]