solution v1.0.2 Solution View Source
A Macro-based approach to working with ok/error tuples
This module exposes two main things:
- guard-clause macros
is_ok/1,is_error/1andis_okerror/1(as well as arity-2 variants of the same), to be used whenever you like. scase/2andswith/2, replacements forcaseandwith-statements respectively that allow you to pattern match on ok/error tuples more effectively, as well as bind to one ore multiple of the values stored inside.
Link to this section Summary
Functions
Matches any error datatype.
Matches {:error, res} (as well as tuples with more elements). res is then bound.
Turns a nillable type (that can be either nil or a non-nil value) into an ok/error tuple.
Changes an :ok into an :error, an {:ok, ...} into an {:error, ...} and vice-versa.
Matches when x is one of the following
Matches when x is a long-enough ok-tuple that has more than n_elems elements.
Matches when x is one of the following
Matches when x is a long-enough ok-tuple that has more than n_elems elements.
Matches when either is_ok(x) or is_error(x) matches.
Matches when x is a long-enough ok-tuple that has more than n_elems elements.
Matches any ok datatype.
Matches {:ok, res} (as well as tuples with more elements). res is then bound.
Matches any ok/error datatype.
Matches any ok or error type. tag is then bound to :ok or :error.
Matches {:ok, res}, {:error, res} (as well as tuples with more elements). tag and res are bound.
Works like a normal case-statement,
but will expand ok(), error() and okerror()macros to the left side of ->.
Works like a normal with-statement,
but will expand ok(), error() and okerror() macros to the left side of <-.
Link to this section Functions
error() View Source (macro)
Matches any error datatype.
(See also is_error/1)
Has to be used inside the LHS of a scase or swith statement.
error(res) View Source (macro)
Matches {:error, res} (as well as tuples with more elements). res is then bound.
(See also is_error/1)
Has to be used inside the LHS of a scase or swith statement.
from_nillable(thing) View Source
Turns a nillable type (that can be either nil or a non-nil value) into an ok/error tuple.
Also handles Erlang's 'nil'-type equivalent: the atom :undefined.
iex> from_nillable(nil)
{:error, nil}
iex> from_nillable(42)
{:ok, 42}
iex> (%{a: "yes!"} |> Map.get(:a) |> from_nillable())
{:ok, "yes!"}
iex> (%{a: "yes!"} |> Map.get(:b) |> from_nillable())
{:error, nil}
iex> from_nillable(:undefined)
{:error, :undefined}
invert_okerror(okerror) View Source
Changes an :ok into an :error, an {:ok, ...} into an {:error, ...} and vice-versa.
iex> invert_okerror(:ok)
:error
iex> invert_okerror({:ok, 1,2,3})
{:error, 1,2,3}
iex> invert_okerror({:error, "failure"})
{:ok, "failure"}
iex> invert_okerror("improper datatype")
** (ArgumentError) argument error
is_error(x) View Source (macro)
Matches when x is one of the following:
:error{:error, _}{:error, _, _}or a longer tuple where the first element is the atom
:error. ({:error, ...})iex> is_error(:error) true iex> is_error({:error, 42}) true iex> is_error({:error, "I", "have", "many", "elements"}) true iex> is_error(:asdf) false iex> is_error({:ok, "success!"}) false
is_error(x, n_elems) View Source (macro)
Matches when x is a long-enough ok-tuple that has more than n_elems elements.
is_ok(x) View Source (macro)
Matches when x is one of the following:
:ok{:ok, _}{:ok, _, _}or a longer tuple where the first element is the atom
:ok({:ok, ...})iex> is_ok(:ok) true iex> is_ok({:ok, 42}) true iex> is_ok({:ok, "I", "have", "many", "elements"}) true iex> is_ok(:asdf) false iex> is_ok({:error, "failure"}) false
is_ok(x, n_elems) View Source (macro)
Matches when x is a long-enough ok-tuple that has more than n_elems elements.
is_okerror(x) View Source (macro)
Matches when either is_ok(x) or is_error(x) matches.
iex> is_okerror({:ok, "Yay!"})
true
iex> is_okerror({:error, "Nay"})
true
iex> is_okerror(false)
false
iex> is_okerror({})
false
iex> is_okerror({:ok, "the", "quick", "brown", "fox"})
true
is_okerror(x, n_elems) View Source (macro)
Matches when x is a long-enough ok-tuple that has more than n_elems elements.
Warning: Will not match plain :ok or :error!
ok() View Source (macro)
Matches any ok datatype.
(See also is_ok/1)
Has to be used inside the LHS of a scase or swith statement.
ok(res) View Source (macro)
Matches {:ok, res} (as well as tuples with more elements). res is then bound.
(See also is_ok/1)
Has to be used inside the LHS of a scase or swith statement.
okerror() View Source (macro)
Matches any ok/error datatype.
Has to be used inside the LHS of a scase or swith statement.
okerror(tag) View Source (macro)
Matches any ok or error type. tag is then bound to :ok or :error.
(See also is_okerror/1)
Has to be used inside the LHS of a scase or swith statement.
okerror(tag, res) View Source (macro)
Matches {:ok, res}, {:error, res} (as well as tuples with more elements). tag and res are bound.
(See also is_okerror/1)
tag is bound to the value :ok or :error depending on the tuple.
res is bound to what the second element might be.
Has to be used inside the LHS of a scase or swith statement.
scase(input, conditions) View Source (macro)
Works like a normal case-statement,
but will expand ok(), error() and okerror()macros to the left side of ->.
iex> scase {:ok, 10} do
...> ok() -> "Yay!"
...> _ -> "Failure"
...> end
"Yay!"
You can also pass arguments to ok(), error() or okerror() which will then be bound and available
to be used inside the case expression:
iex> scase {:ok, "foo", 42} do
...> ok(res, extra) ->
...> "result: #{res}, extra: #{extra}"
...> _ ->
...> "Failure"
...> end
"result: foo, extra: 42"
Note that for ok() and error(), the first argument will match the first element after the :ok or :error tag.
On the other hand, for okerror(), the first argument will match the tag :ok or :error.
Note: It is not required to import Solution to use the macros inside swith without prefixing them.
swith(statements, conditions) View Source (macro)
Works like a normal with-statement,
but will expand ok(), error() and okerror() macros to the left side of <-.
iex> x = {:ok, 10}
iex> y = {:ok, 33}
iex> swith ok(res) <- x,
...> ok(res2) <- y do
...> "We have: #{res} #{res2}"
...> else
...> _ -> "Failure"
...> end
"We have: 10 33"
You can also pass arguments to ok(), error() or okerror() which will then be bound and available
to be used inside the rest of the swith-expression:
iex> x = {:ok, 10}
iex> y = {:error, 33}
iex> z = {:ok, %{a: 42}}
iex> swith ok(res) <- x,
...> error(res2) <- y,
...> okerror(tag, metamap) <- z,
...> %{a: val} = metamap do
...> "We have: #{res} #{res2} #{tag} #{val}"
...> else
...> _ -> "Failure"
...> end
"We have: 10 33 ok 42"
Note that for ok() and error(), the first argument will match the first element after the :ok or :error tag.
On the other hand, for okerror(), the first argument will match the tag :ok or :error.
Note: It is not required to import Solution to use the macros inside swith without prefixing them.