Elixir - try/catch vs try/rescue?

elixir

Solution

It's a good question.After research a bit.

What is the differences between them in details?

José's answer:

Mainly, you should use `throw` for control-flow and reserve `raise` for errors, which happens on developer mistakes or under exceptional circumstances.

In Elixir, this distinction is rather theoretical, but they matter in some languages like Ruby, where using errors/exceptions for control-flow is expensive because creating the exception object and backtrace is expensive.

- How should I pick one to use in a specific use case?

Please check this answer Which situations require throw catch in Elixir

Shortly:

`raise/rescue`

Consider raise/rescue to be explicitly about exception handling (some unexpected situation like programmer errors, wrong environment, etc).

`throw/catch`

Is useful in places where you have expected failures. Classic examples are:

- exiting a deeply nested recursive call: https://github.com/devinus/poison/blob/master/lib/poison/parser.ex#L34-L46

- normal error handling is too expensive (can occur in too many places): https://github.com/michalmuskala/mongodb_ecto/blob/master/lib/mongo_ecto/objectid.ex#L29-L43

- you have an non-local construct (like transactions): https://github.com/elixir-lang/ecto/blob/428126157b1970d10f9d5233397f07c35ce69cac/test/support/test_repo.exs#L84-L98

The last one:

- What exactly are 'the situations where it is not possible to retrieve a value unless by using throw and catch'?

Let's say you are trying to running some code from a process that is supervised by a `Supervisor` but the process dies for an unexpected reason.

try do
IO.inspect MayRaiseGenServer.maybe_will_raise
rescue
  RuntimeError -> IO.puts "there was an error"
end

`MayRaiseGenServer` is supervised by a `Supervisor` and for some reason an error was raised:

try do
IO.inspect MayRaiseGenServer.maybe_will_raise # <- Code after this line is no longer executed

And then you can come up with using catch an exception here:

try do
  IO.inspect MayRaiseGenServer.maybe_will_raise
catch
  :exit, _ -> IO.puts "there was an error"
end

Ok.Hope that clarify enough what we are looking for.

Problem

Background Both `try/rescue` and `try/catch` are error handling techniques in Elixir. According the corresponding chapter in the introduction guide. Errors can be rescued using the `try/rescue` construct On the other hand, `throw` and `catch` are reserved for situations where it is not possible to retrieve a value unless by using `throw` and `catch`. Doubts I have a brief understanding that `rescue` is for errors. While `catch` is for any value. However, - When should I make use of the error handling mechanisms in Elixir? - What are the differences between them in detail? - How should I pick one to use in a specific use case? - What exactly are 'the situations where it is not possible to retrieve a value unless by using `throw` and `catch`'?

Original source

Related problems