## 8.20 Try

try Exprscatch    Class1:ExceptionPattern1[:Stacktrace] [when ExceptionGuardSeq1] ->        ExceptionBody1;    ClassN:ExceptionPatternN[:Stacktrace] [when ExceptionGuardSeqN] ->        ExceptionBodyNend

This is an enhancement of catch. It gives the possibility to:

• Distinguish between different exception classes.
• Choose to handle only the desired ones.
• Passing the others on to an enclosing try or catch, or to default error handling.Notice that although the keyword catch is used in the try expression, there is not a catch expression within the try expression.

It returns the value of Exprs (a sequence of expressions Expr1, …, ExprN) unless an exception occurs during the evaluation. In that case the exception is caught and the patterns ExceptionPattern with the right exception class Class are sequentially matched against the caught exception. If a match succeeds and the optional guard sequence ExceptionGuardSeq is true, the corresponding ExceptionBody is evaluated to become the return value.

Stacktrace, if specified, must be the name of a variable (not a pattern). The stack trace is bound to the variable when the corresponding ExceptionPattern matches.

If an exception occurs during evaluation of Exprs but there is no matching ExceptionPattern of the right Class with a true guard sequence, the exception is passed on as if Exprs had not been enclosed in a try expression.

If an exception occurs during evaluation of ExceptionBody, it is not caught.

It is allowed to omit Class and Stacktrace. An omitted Class is shorthand for throw:

try Exprscatch    ExceptionPattern1 [when ExceptionGuardSeq1] ->        ExceptionBody1;    ExceptionPatternN [when ExceptionGuardSeqN] ->        ExceptionBodyNend

The try expression can have an of section:

try Exprs of    Pattern1 [when GuardSeq1] ->        Body1;    ...;    PatternN [when GuardSeqN] ->        BodyNcatch    Class1:ExceptionPattern1[:Stacktrace] [when ExceptionGuardSeq1] ->        ExceptionBody1;    ...;    ClassN:ExceptionPatternN[:Stacktrace] [when ExceptionGuardSeqN] ->        ExceptionBodyNend

If the evaluation of Exprs succeeds without an exception, the patterns Pattern are sequentially matched against the result in the same way as for a case expression, except that if the matching fails, a try_clause run-time error occurs.

An exception occurring during the evaluation of Body is not caught.

The try expression can also be augmented with an after section, intended to be used for cleanup with side effects:

try Exprs of    Pattern1 [when GuardSeq1] ->        Body1;    ...;    PatternN [when GuardSeqN] ->        BodyNcatch    Class1:ExceptionPattern1[:Stacktrace] [when ExceptionGuardSeq1] ->        ExceptionBody1;    ...;    ClassN:ExceptionPatternN[:Stacktrace] [when ExceptionGuardSeqN] ->        ExceptionBodyNafter    AfterBodyend

AfterBody is evaluated after either Body or ExceptionBody, no matter which one. The evaluated value of AfterBody is lost; the return value of the try expression is the same with an after section as without.

Even if an exception occurs during evaluation of Body or ExceptionBody, AfterBody is evaluated. In this case the exception is passed on after AfterBody has been evaluated, so the exception from the try expression is the same with an after section as without.

If an exception occurs during evaluation of AfterBody itself, it is not caught. So if AfterBody is evaluated after an exception in Exprs, Body, or ExceptionBody, that exception is lost and masked by the exception in AfterBody.

The of, catch, and after sections are all optional, as long as there is at least a catch or an after section. So the following are valid try expressions:

try Exprs of     Pattern when GuardSeq ->         Body after     AfterBody end try Exprscatch     ExpressionPattern ->         ExpressionBodyafter    AfterBodyend try Exprs after AfterBody end

Next is an example of using after. This closes the file, even in the event of exceptions in file:read/2 or in binary_to_term/1. The exceptions are the same as without the try…after…end expression:

termize_file(Name) ->    {ok,F} = file:open(Name, [read,binary]),    try        {ok,Bin} = file:read(F, 1024*1024),        binary_to_term(Bin)    after        file:close(F)    end.

Next is an example of using try to emulate catch Expr:

try Exprcatch    throw:Term -> Term;    exit:Reason -> {'EXIT',Reason}    error:Reason:Stk -> {'EXIT',{Reason,Stk}}end