[erlang-questions] Local namespaces in case/try

Jesper Louis Andersen <>
Mon Jul 16 17:19:43 CEST 2012

On Jul 16, 2012, at 1:47 AM, Richard O'Keefe wrote:

> test(Input) ->
>    try do_something(test2(test1(Input)))
>    catch {error,E} -> do_something_on_error(E)
>    end.

This is *the* way to structure this code. The observation is that failure of one pattern leads to failure of the them all. This tells you that your code lives in an error-monad. The way to get hold of such a monad in Erlang is to use a try…catch construct because it is really an exceptional structure.

If you are really lucky, any failure will just lead to the process exiting and you don't have to handle that specifically. Then something is to be said for just structuring the code like

R = do_something(test2(test1(Input))).

And let the crash be handled directly. Usually the pattern reveals itself when you have deeply nested levels of case constructs where the error is just passed on if it happens. The trick is to rewrite it into a try-catch (and be precise about what error classes you catch. Don't catch them all - i.e., do Pokemon® coding).

Another solution is to utilize the fact that case is an expression, not a statement. So you can fold functions over the accumulated result:

lists:foldl(fun(F, {error, E}) -> {error, E}; (F, {ok, V}) -> F(V) end, {ok, Input}, [fun test1/1, fun test2/1]).

(not tested). Essentially, this is the same thing as the try..catch. Going further, one could seek to add enough syntactic sugar to support something like the Haskell do-notation - but it won't be as neat as in Haskell because we have no type information in type classes to implicitly choose the right monad to operate in[1]


[1] Aside: This is really what the power of Haskell is about. Using the type system to *avoid* having to write boring code. And use the type system to *substitute* the code executed automatically so save you time when your program changes.

More information about the erlang-questions mailing list