Az ERLANG programozási nyelv

Kivételkezelés

Szintaxis

try Exprs of Pattern1 [when GuardSeq1] -> Body1; ...; PatternN [when GuardSeqN] -> BodyN catch [Class1:]ExceptionPattern1 [when ExceptionGuardSeq1] -> ExceptionBody1; ...; [ClassN:]ExceptionPatternN [when ExceptionGuardSeqN] -> ExceptionBodyN after AfterBody end

Az of, catch, after szekciók opcionálisak, mindaddig, amíg megtalálható a catch vagy az after rész. Így a következők is helyes kifejezések:

try Exprs of Pattern when GuardSeq -> Body after AfterBody end ... try Exprs catch ExpressionPattern -> ExpressionBody after AfterBody end ... try Exprs after AfterBody end

Másrészt kivételeket a throw(...)-val lehet kiváltani, ahol a "..." helyére tetszőleges term írható.

Használat

Catch és throw

A catch és throw eszközök kifejezés-kiértékelés felügyeletére adnak módot. Kifejezés-kiértékelés során fellépő hiba alapértelmezett hatása, hogy a kifejezést kiértékelő processz abnormálisan terminál. Ez a viselkedés catch bevezetésével módosítható, a következőképpen: A catch Kifejezes utasítás a Kifejezes értékét adja vissza, ha a kiértékelés közben nem lép fel hiba. Ellenkező esetben visszatérési értéke sor típusú, {‘EXIT’,Hiba_oka}, ahol az utóbbi sorelem a hiba okáról tájékoztató atom. A vezérlés a függvényt hívóhoz rendszerint a kiértékelés végeztével adódik vissza. Viszont ha egy throw/1 kiértékelésére kerül sor, a vezérlés azonnal visszakerül a catch-hez. Mivel a catch-ek egymásba ágyazhatóak, itt a legutoljára kiadott catch Kifejezés hívásról van szó. A throw/1 kiértékelés futás-idejű hibát ad, ha nem a kiértékelés nem catch klózban történik.

Catch és throw használata hibás kód elleni védelemre

Egy egyszerű ERLANG shell a következő módon írható:

-module(s_shell). -export([go/0]). go()-> eval(io:parser_exprs(‘=> ‘)), % ‘=>’ a prompt go(). eval({form,Exprs}) -> case catch eval:exprs(Exprs, []) of {‘EXIT’, What} -> io:format("Error: ~w!~n", [What]); {value, What, _} -> io:format("Error: ~w!~n", [What]) end; eval(_) -> io:format("Syntax error!~n", []).

Az io:parse_expr/1 standard könyvtári függvény beolvas és kiértékel egy ERLANG kifejezést és {form, Exprs} listát ad vissza, ha a kifejezés helyes. Ez esetben az eval/1 első mintája illeszkedik, és meghívjuk az eval:exprs/2 függvényt a kifejezés kiértékelésére. Ezt egy catch-en belül tesszük, hiszen nem tudhatjuk, hogy a kifejezéskiértékelés dob-e kivételt vagy sem. A catch kifejezéshez hiba esetén az {‘EXIT’, What}, sikeres kiértékelés esetén a {value, What, _} minta illeszkedik.

Catch és throw használata függvényhívásból való különleges visszatérésre

Tekintsük a következő példát, mely integer listákat képes felismerni:

parse_list([‘[‘,’]’|T) -> {nil, T}; parse_list([‘[‘,X|T) when integer(X) -> {Tail, T1} = parse_list_tail(T), {{cons, X, Tail}, T1}; parse_list(X) -> throw({illegal_token, X}). parse_list_tail([‘,’,X|T]) when integer(X) -> {Tail, T1} = parse_list_tail(T), {{cons, X, Tail}, T1}; parse_list_tail([‘]’|T) -> {nil, T|; parse_list_tail1(X) -> throw({illegal_list_tail, X}).

A következő függvényhívás:

> catch parse_list([‘[‘,12,’,’,a]). {illegal_list_tail,[‘,’,a])

Látható, hogy a rekurzió menetét megkerülve jutottunk ki a rekurzióból.