Sono nuovo di Erlang, ma ecco come penso a cosa sono queste cose, le loro differenze, quello che stanno utilizzati per, ecc .:
throw
: una condizione che deve essere maneggiato a livello locale (ad esempio all'interno del processo corrente). Per esempio. il chiamante sta cercando un elemento in una raccolta, ma non sa se la raccolta contiene effettivamente un tale elemento; quindi, il destinatario potrebbe lanciare se tale elemento non è presente e il chiamante rilevare l'assenza utilizzando try[/of]/catch
. Se chiamante trascura di fare questo, allora questo viene trasformato in un nocatch
error
(spiegato qui di seguito).
exit
: L'attuale processo è fatto. Per esempio. ha semplicemente finito (in quel caso, ci si passa normal
, che è considerato il uguale alla funzione originale di ritorno), o il suo funzionamento è stato annullato (per esempio normalmente loop a tempo indeterminato, ma ha appena ricevuto un messaggio shut_down
).
error
: il processo ha fatto qualcosa e/o ha raggiunto uno stato che il programmatore non ha tenuto in considerazione (ad esempio 1/0), ritiene impossibile (ad esempio case ... of
riscontra un valore che non corrisponde ad alcun caso), oppure non è soddisfatta una condizione preliminare (ad esempio, l'input non è vuoto). In questo caso, il recupero locale non ha senso. Pertanto, né lo throw
né lo exit
sono appropriati. Poiché ciò è inaspettato, una traccia dello stack fa parte del Motivo.
Come si può vedere, l'elenco è in ordine crescente:
throw
è per condizioni sane che il chiamante si aspetta da gestire. Cioè la gestione avviene entro il il processo corrente.
exit
è anche sano, ma dovrebbe terminare il processo corrente semplicemente perché il processo è terminato.
error
è folle. È successo qualcosa che non può essere ragionevolmente recuperato da (di solito un bug?), E il ripristino locale non sarebbe appropriato.
vs. altre lingue:
throw
è analogo al modo in cui le eccezioni controllate sono utilizzate in Java. Considerando che, error
viene utilizzato in un modo più analogo alle eccezioni non controllate. Le eccezioni controllate sono eccezioni che il chiamante deve gestire. Java richiede di eseguire il wrap delle chiamate in try/catch
o dichiarare che il metodo è throws
tali eccezioni. Mentre le eccezioni non controllate si propagano generalmente al chiamante più esterno.
exit
non ha un buon analogico in più lingue "convenzionali" come Java, C++, Python, JavaScript, Ruby, ecc exit
vagamente come un uber- return
: invece di restituire alla fine, si può tornare dal al centro di una funzione, eccetto che non si ritorna solo dalla funzione corrente, si ritorna da tutti ALL.
exit
Esempio
serve_good_times() ->
receive
{top_of_the_mornin, Sender} ->
Sender ! and_the_rest_of_the_day_to_yourself;
{you_suck, Sender} ->
Sender ! take_a_chill_pill;
% More cases...
shut_down ->
exit(normal)
end,
serve_good_times()
end
Dal serve_good_times
chiamate se stesso dopo quasi tutti i messaggi, il programmatore ha deciso che non vogliamo ripetere quella chiamata in ogni caso ricevere. Pertanto, ha effettuato la chiamata dopo il alla ricezione. Ma allora, che succede se serve_good_times
decide di smettere di chiamarsi? Questo è dove exit
viene in soccorso. Passando da normal
a exit
, il processo termina come se fosse stata restituita l'ultima chiamata di funzione.
Come tale, è in genere inappropriato chiamare exit
in una libreria generica, ad esempio lists
. Nessuna delle attività della biblioteca è se il processo debba terminare; che dovrebbe essere deciso dal codice dell'applicazione.
Informazioni su Anormale exit
?
Questo è importante se un altro processo (il processo "a distanza") è legata al processo di "locale" che chiama exit
(e process_flag(trap_exit, true)
non è stato chiamato): Proprio come l'ultima funzione che restituisce, exit(normal)
non causa processo remoto per uscire . Ma se il processo locale effettua una chiamata exit(herp_derp)
, anche il processo remoto viene chiuso con Reason=herp_derp
. Naturalmente, se il processo remoto è collegato a più processi, ottengono anche il segnale di uscita con Reason=herp_derp
. Pertanto, le uscite non normal
provocano una reazione a catena.
Diamo uno sguardo a questo in azione:
1> self().
<0.32.0>
2> spawn_link(fun() -> exit(normal) end).
<0.35.0>
3> self().
<0.32.0>
4>
4>
4> spawn_link(fun() -> exit(abnormal) end).
** exception exit: abnormal
5> self().
<0.39.0>
6>
Il primo processo che abbiamo procreati non ha causato il guscio per uscire (possiamo dire, perché self
restituito lo stesso PID prima e dopo spawn_link
). MA il secondo processo ha fatto uscire la shell (e il sistema ha sostituito il processo shell con uno nuovo).
Ovviamente, se il processo remoto utilizza process_flag(trap_exit, true)
, viene visualizzato solo un messaggio, indipendentemente dal fatto che il processo locale passi normal
o altro al numero exit
. L'impostazione di questo flag interrompe la reazione a catena.
6> process_flag(trap_exit, true).
false
7> spawn_link(fun() -> exit(normal) end).
<0.43.0>
8> self().
<0.39.0>
9> flush().
Shell got {'EXIT',<0.43.0>,normal}
ok
10>
10>
10> spawn_link(fun() -> exit(abnormal) end).
<0.47.0>
11> self().
<0.39.0>
12> flush().
Shell got {'EXIT',<0.47.0>,abnormal}
Ricordiamo che ho detto che exit(normal)
viene trattato come la funzione originale di ritorno:
13> spawn_link(fun() -> ok end).
<0.51.0>
14> flush().
Shell got {'EXIT',<0.51.0>,normal}
ok
15> self().
<0.39.0>
che ne sai: la stessa cosa è successa come quando exit(normal)
è stato chiamato. Meraviglioso!
Grazie mille per il vostro aiuto. Adesso è più chiaro. –
@ChenYu - mi scuso per la mia spiegazione sciatta. rvirding: grazie per averlo chiarito. Permettetemi di risolvere/cancellare la mia risposta - minore confusione, meglio è! – Faiz