Exceptions in Elixir are basically records. You can define your own exceptions by creating a module. Inside it, use defexception to define the various fields in the exception, along with their default values. Because you’re creating a module, you can also add functions—often these are used to format the exception’s fields into meaningful messages.
Say we’re writing a library to talk to a Microsoft Kinect controller. It might want to raise an exception on various kinds of communication errors. Some of these are permanent, but others are likely to be transient and can be retried. We’ll define our exception with its (required) message field and an additional can_retry field. We’ll also add a function that formats these two fields into a nice message.
| defmodule KinectProtocolError do |
| |
| defexception message: "Kinect protocol error", |
| can_retry: false |
| |
| def full_message(me) do |
| "Kinect failed: #{me.message}, retriable: #{me.can_retry}" |
| end |
| |
| end |
Users of our library could write code like this:
| try do |
| talk_to_kinect() |
| rescue |
| error in [KinectProtocolError] -> |
| IO.puts KinectProtocolError.full_message(error) |
| if error.can_retry, do: schedule_retry() |
| end |
If an exception gets raised, the code handles it and possibly retries:
| Kinect failed: usb unplugged, retriable: true |
| Retrying in 10 seconds |