Current section
Files
Jump to
Current section
Files
lib/exceptional/control.ex
defmodule Exceptional.Control do
@moduledoc ~S"""
Exception control flow
## Convenience `use`s
Everything:
use Exceptional.Control
"""
defmacro __using__(_) do
quote do
import unquote(__MODULE__)
end
end
@doc ~S"""
Branch on if the value is an `Exception`, applying the associated function for
that case. Does not catch thrown exceptions.
## Examples
iex> use Exceptional.Control
...> branch 1,
...> value_do: fn v -> v + 1 end.(),
...> exception_do: fn ex -> ex end.()
2
iex> use Exceptional.Control
...> branch ArgumentError.exception("error message"),
...> value_do: fn v -> v end.(),
...> exception_do: fn %{message: msg} -> msg end.()
"error message"
iex> use Exceptional.Control
...> branch Enum.fetch!([], 99),
...> value_do: fn v -> v + 1 end.(),
...> exception_do: fn ex -> ex end.()
** (Enum.OutOfBoundsError) out of bounds error
"""
defmacro branch(maybe_exception, [value_do: value_do, exception_do: exception_do]) do
quote do
maybe_exc = unquote(maybe_exception)
if Exception.exception?(maybe_exc) do
maybe_exc |> unquote(exception_do)
else
maybe_exc |> unquote(value_do)
end
end
end
@doc ~S"""
Alias for `Exceptional.Control.branch`
## Examples
iex> use Exceptional.Control
...> if_exception 1, do: fn ex -> ex end.(), else: fn v -> v + 1 end.()
2
iex> use Exceptional.Control
...> if_exception ArgumentError.exception("error message") do
...> fn %{message: msg} -> msg end.()
...> else
...> fn v -> v end.()
...> end
"error message"
iex> use Exceptional.Control
...> ArgumentError.exception("error message")
...> |> if_exception do
...> fn %{message: msg} -> msg end.()
...> else
...> fn v -> v end.()
...> end
"error message"
"""
defmacro if_exception(maybe_exception, do: exception_do, else: value_do) do
quote do
maybe_exc = unquote(maybe_exception)
if Exception.exception?(maybe_exc) do
maybe_exc |> unquote(exception_do)
else
maybe_exc |> unquote(value_do)
end
end
end
end