josevalim/elixir — Issue #97: Build a record base exception system
Author: josevalim
Created: 2012-01-10 12:30:38+00:00
State: open

Today, Elixir exception handling mechanism are simply a direct translation of Erlang mechanism:

try do
do_something_dangerous()
catch: { :error, :badarg, _ }
# Handle the error
end

I want to propose an exception system based on records using begin/rescue (similar to Ruby) to handle such errors. The syntax for this new system would be:

begin do
do_something_dangerous()
rescue: BadArgument = e
# Handle the error
end

Where BadArgument would be a record like (the exception class could also add other record fields):

{ ::BadArgument, MESSAGE, STACKTRACE }

This schema has some benefits:

1) We are no longer matching against a tuple as in { :badmatch, contents } or against an atom as in :badarg. This means someone can change the exception record to add new fields without affecting existing code written (we only care about the first element).

2) We provide a default mechanism to add exception messages. Erlang errors are very hard to handle because they usually contain no message attached to the error explaining what the error is about.

But it also has some downsides:

1) We are no going to wrap Erlang exceptions. So all Erlang original errors: :case_clause, :badarg and :undef can still pop-up. This may force users to write code like this:

try do
begin do
do_something_dangerous()
rescue: SomeElixirException = e
# Handle the error
end
catch: { :error, :some_erlang_exception, _ }
# Handle the error
end

One possible alternative to handle this problem is to avoid adding a new macro named begin, but simply make rescue a part of the try/catch handling (which I actually prefer more):

try do
do_something_dangerous()
rescue: SomeElixirException = e
# Handle the error
catch: { :error, :some_erlang_exception, _ }
# Handle the error
end

What do you guys think? /cc @andrzejsliwa @tarcieri