Erlang - Eccezioni

La gestione delle eccezioni è richiesta in qualsiasi linguaggio di programmazione per gestire gli errori di runtime in modo da poter mantenere il normale flusso dell'applicazione. L'eccezione normalmente interrompe il normale flusso dell'applicazione, motivo per cui è necessario utilizzare la gestione delle eccezioni nella nostra applicazione.

Normalmente quando si verifica un'eccezione o un errore in Erlang, verrà visualizzato il seguente messaggio.

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

Il crash dump verrà scritto in -

erl_crash.dump
init terminating in do_boot ()

A Erlang, ci sono 3 tipi di eccezioni:

  • Error - Sto chiamando erlang:error(Reason)terminerà l'esecuzione nel processo corrente e includerà una traccia dello stack delle ultime funzioni chiamate con i loro argomenti quando lo catturi. Questi sono i tipi di eccezioni che provocano gli errori di runtime di cui sopra.

  • Exists- Esistono due tipi di uscite: uscite "interne" e uscite "esterne". Le uscite interne vengono attivate chiamando la funzioneexit/1e fare in modo che il processo corrente interrompa la sua esecuzione. Le uscite esterne vengono chiamate conexit/2 e hanno a che fare con più processi nell'aspetto simultaneo di Erlang.

  • Throw- Un lancio è una classe di eccezione utilizzata per i casi che ci si può aspettare che il programmatore gestisca. In confronto alle uscite e agli errori, non portano davvero alcun "arresto anomalo del processo!" intenti dietro di loro, ma piuttosto controllano il flusso. Dato che usi i lanci aspettandoti che il programmatore li gestisca, di solito è una buona idea documentarne l'uso all'interno di un modulo che li utilizza.

UN try ... catch è un modo per valutare un'espressione permettendoti di gestire il caso positivo e gli errori riscontrati.

La sintassi generale di un'espressione try catch è la seguente.

Sintassi

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

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

L'espressione in mezzo try and ofsi dice che sia protetto. Ciò significa che verrà catturata qualsiasi tipo di eccezione che si verifica all'interno di quella chiamata. I modelli e le espressioni tra i filetry ... of and catch si comportano esattamente nello stesso modo di un file case ... of.

Infine, la parte di cattura: qui puoi sostituire TypeOfErrorper errore, lancio o uscita, per ogni rispettivo tipo che abbiamo visto in questo capitolo. Se non viene fornito alcun tipo, viene assunto un lancio.

Di seguito sono riportati alcuni degli errori e dei motivi di errore in Erlang:

Errore Tipo di errore
badarg Brutta discussione. L'argomento è di tipo di dati errato o è altrimenti formato male.
badarith Argomento errato in un'espressione aritmetica.
{badmatch, V} Valutazione di un'espressione di corrispondenza non riuscita. Il valore V non corrisponde.
function_clause Nessuna clausola di funzione corrispondente viene trovata durante la valutazione di una chiamata di funzione.
{case_clause, V} Nessun ramo corrispondente viene trovato durante la valutazione di un'espressione case. Il valore V non corrisponde.
se la clausola Non viene trovato alcun ramo vero durante la valutazione di un'espressione if.
{try_clause, V} Nessun ramo corrispondente viene trovato durante la valutazione della sezione di un'espressione try. Il valore V non corrisponde.
undef Impossibile trovare la funzione durante la valutazione di una chiamata di funzione.
{badfun, F} Qualcosa non va con una F divertente
{badarity, F} Un divertimento viene applicato al numero sbagliato di argomenti. F descrive il divertimento e gli argomenti.
timeout_value Il valore di timeout in un'espressione receive..after viene valutato su un valore diverso da un numero intero o infinito.
noproc Tentativo di collegamento a un processo inesistente.

Di seguito è riportato un esempio di come queste eccezioni possono essere utilizzate e di come vengono eseguite le operazioni.

  • La prima funzione genera tutti i possibili tipi di eccezione.

  • Quindi scriviamo una funzione wrapper da chiamare generate_exception in un tentativo ... cattura l'espressione.

Esempio

-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 eseguiamo il programma come helloworld: demo (). , otterremo il seguente output -

Produzione

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