Exceptions
| Raise | |
| Rescue | |
| After always runs | |
| Your own exception |
Raise
The raise call stops the current process with an exception struct. A plain string becomes a RuntimeError carrying that message, while naming a module with a message raises that exact type. Uncaught exceptions end the process and print a report.
raise "boom"
raise ArgumentError, "bad input"
Rescue
The try block marks risky code and the rescue branch handles the failure by exception type. Matching on the module keeps expected failures apart from surprise bugs. The bound variable carries the struct, so the message function of the Exception module reads its text.
try do
raise "boom"
rescue
e in RuntimeError -> IO.puts(Exception.message(e))
end
boom
After always runs
The after block holds cleanup that runs on every path: after success, after a rescued failure, and even when an unexpected error escapes. Closing files and releasing locks belongs there, never inside the main body.
try do
raise "boom"
rescue
_e in RuntimeError -> IO.puts("caught")
after
IO.puts("cleanup")
end
caught
cleanup
Your own exception
The defexception macro defines an exception module with the fields you list. Raising it with a message builds the struct, and rescuing by module name keeps domain failures apart from ordinary bugs. Give the module a clear name so future readers grasp the rescue at a glance.
defmodule AppError do
defexception [:message]
end
raise AppError, message: "nope"
Next: ok and error tuples
Article author: Arthur Isaev