Elixir Raising and Rescuing
Raising is stopping the current work by throwing an error with a message. Rescuing is catching that error so the program can react and carry on.
A rescued raise prints its message
The raise throws an error before the line after it can run. The rescue branch catches it and prints its message.
try do
raise "boom"
rescue
e -> IO.puts(Exception.message(e))
endThe program continues after a rescue
Checker raises for a negative score and returns the score otherwise. The rescue prints the message, and the line after the block still runs.
defmodule Checker do
def check(score) when score < 0, do: raise("negative score")
def check(score), do: score
end
try do
IO.puts(Checker.check(-1))
rescue
e -> IO.puts("Rescued: #{Exception.message(e)}")
end
IO.puts("Program continues")Rescue can supply a fallback value
A try block is an expression, so it can return a value. Here the rescue branch builds the fallback text from the message.
result =
try do
raise "missing name"
rescue
e -> "Fallback for: #{Exception.message(e)}"
end
IO.puts(result)Example
defmodule Signup do
def require_name(name) when name == "", do: raise("name is empty")
def require_name(name), do: name
end
try do
IO.puts("Saved: #{Signup.require_name("Ana")}")
rescue
e -> IO.puts("Cannot save: #{Exception.message(e)}")
end
try do
IO.puts("Saved: #{Signup.require_name("")}")
rescue
e -> IO.puts("Cannot save: #{Exception.message(e)}")
end
IO.puts("Done")Key points
- RuntimeError: the standard error created by raise, carrying the text given to it.
- Raise: raise "text" stops the code at that point and throws the error upward.
- Flow: an error nobody rescues stops the whole script.
- Try: code inside a try block runs until it finishes or raises an error.
- Rescue: the rescue branch runs when the try code raises an error.
- Message: Exception.message(e) returns the text stored in the rescued error.
In this example, the first try block saves Ana because require_name returns the name. The second call raises "name is empty", so its rescue branch prints the cannot-save line. The final line still prints, which shows the program carried on.
Note
rescue suits rare failures, while expected failures often return {:error, reason} tuples instead.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
After raise "boom" is rescued as e, what does Exception.message(e) return?