View Source Fey.Result (Fey v0.0.2)
The module provides functions to work with a well-established pattern of result tuples
(sometimes called "tagged tuples") in Elixir. By them we mean {:ok, value}
or {:error, error}
tuples.
Fey.Result
adds a bunch of convenience to work with these, especially in pipelines. They can replace
with
chains, which are frowned upon by some people in the Elixir community. Let's see an example:
Repo.fetch(OrderLineItem, 123)
|> Fey.Result.map(& &1.sku)
|> Fey.Result.bind(&Repo.get_by(Product, sku: &1) |> Fey.Result.wrap_not_nil(:sku_not_found))
|> Fey.Result.map(& &1.name)
This either returns a name of the product for line item (matches by SKU) or any of the intermediate
errors that might happpen: {:ok, :not_found}
(from Repo.fetch
) or {:error, :sku_not_found}
.
Summary
Functions
If the result is a success, returns a value of fun applied on result's value. It's analogous to map/2
, but does not wrap
in {:ok, val}
automatically, which makes it useful if fun returns a result.
Inverse of bind/2
- if the result is an error, executes fun and returns its result.
If the result is an error, return its details.
Returns whether or not the passed value is an error.
If the result is a success, returns its value.
If the result is a success, return its value but if the result is an error, return default value
instead of raising exception (like get!/1
does).
If the result is a success, returns {:ok, val}
, where val
is a return value of fun applied on result's value.
Returns whether or not the passed value is a success. Raises Fey.Result.BadArgument if the value is not a valid result tuple.
Wraps a value in a success result tuple (i.e. {:ok, value}
).
Similar to wrap/1
, but only returns a success result if the passed value is not nil
.
If it is, {:error, error}
is returned, where error
is either passed as a second
argument, or by default is :not_found
.
Types
Functions
If the result is a success, returns a value of fun applied on result's value. It's analogous to map/2
, but does not wrap
in {:ok, val}
automatically, which makes it useful if fun returns a result.
If the result is an error, returns error itself.
Raises Fey.Result.BadArgument
if the value passed as argument is not a valid result tuple.
Examples
iex> Fey.Result.bind({:ok, 42}, fn v -> {:ok, v / 2} end)
{:ok, 21.0}
iex> Fey.Result.bind({:ok, 42}, fn v -> v / 2 end)
21.0
iex> Fey.Result.bind({:error, :not_found}, fn v -> {:ok, v / 2} end)
{:error, :not_found}
iex> Fey.Result.bind(:some_atom, fn v -> {:ok, v / 2} end)
** (Fey.Result.BadArgument) :some_atom is not a valid result tuple
Inverse of bind/2
- if the result is an error, executes fun and returns its result.
If the result is success, just returns it.
Raises Fey.Result.BadArgument
if the value passed as argument is not a valid result tuple.
This function makes most sense when used in a pipeline where you want to take the first successful result. For example:
parse_as_iso_datetime(input)
|> Fey.Result.bind_error(fn -> parse_as_iso_date(input) end)
|> Fey.Result.bind_error(fn -> parse_as_naive_datetime(input) end)
|> Fey.Result.bind_error(fn -> parse_as_naive_date(input) end)
# {:ok, parsed_date} | {:error, :bad_format}
Examples
iex> Fey.Result.bind_error({:error, :not_found}, fn -> {:ok, 42} end)
{:ok, 42}
iex> Fey.Result.bind_error({:ok, nil}, fn -> {:ok, 42} end)
{:ok, nil}
iex> Fey.Result.bind_error(nil, fn -> {:ok, 42} end)
** (Fey.Result.BadArgument) nil is not a valid result tuple
If the result is an error, return its details.
Raises NotError if the result is not errorneous.
Raises Fey.Result.BadArgument
is the value passed as argument is not a valid result tuple.
Examples
iex> Fey.Result.error!({:error, :not_found})
:not_found
iex> Fey.Result.error!({:ok, 42})
** (Fey.Result.NotError) {:ok, 42} is not an error
iex> Fey.Result.error!(:some_atom)
** (Fey.Result.BadArgument) :some_atom is not a valid result tuple
Returns whether or not the passed value is an error.
Raises Fey.Result.BadArgument if the value is not a valid result tuple.
Examples
iex> Fey.Result.error?({:ok, true})
false
iex> Fey.Result.error?({:error, :not_found})
true
iex> Fey.Result.error?(42)
** (Fey.Result.BadArgument) 42 is not a valid result tuple
If the result is a success, returns its value.
Raises Fey.Result.NotSuccess
if the result is not successful.
Raises Fey.Result.BadArgument
if the value passed as argument is not a valid result tuple.
Examples
iex> Fey.Result.get!({:ok, 42})
42
iex> Fey.Result.get!({:error, :not_found})
** (Fey.Result.NotSuccess) {:error, :not_found} is not a success
iex> Fey.Result.get!(:some_atom)
** (Fey.Result.BadArgument) :some_atom is not a valid result tuple
If the result is a success, return its value but if the result is an error, return default value
instead of raising exception (like get!/1
does).
Raises Fey.Result.BadArgument
if the value passed as argument is not a valid result tuple.
Examples
iex> Fey.Result.get_with_default({:ok, 42}, 1567)
42
iex> Fey.Result.get_with_default({:error, :not_found}, 1567)
1567
iex> Fey.Result.get_with_default("string", 1567)
** (Fey.Result.BadArgument) "string" is not a valid result tuple
If the result is a success, returns {:ok, val}
, where val
is a return value of fun applied on result's value.
If the result is an error, returns error itself.
Raises Fey.Result.BadArgument
if the value passed as argument is not a valid result tuple.
Examples
iex> Fey.Result.map({:ok, 42}, fn v -> v / 2 end)
{:ok, 21.0}
iex> Fey.Result.map({:error, :not_found}, fn v -> v / 2 end)
{:error, :not_found}
iex> Fey.Result.map(:some_atom, fn v -> v / 2 end)
** (Fey.Result.BadArgument) :some_atom is not a valid result tuple
Returns whether or not the passed value is a success. Raises Fey.Result.BadArgument if the value is not a valid result tuple.
Examples
iex> Fey.Result.ok?({:ok, true})
true
iex> Fey.Result.ok?({:error, :not_found})
false
iex> Fey.Result.ok?(42)
** (Fey.Result.BadArgument) 42 is not a valid result tuple
Wraps a value in a success result tuple (i.e. {:ok, value}
).
Note that it does not check whether a value passed as argument is already a valid result tuple, or not.
Examples
iex> Fey.Result.wrap(true)
{:ok, true}
iex> Fey.Result.wrap({:ok, "fourty two"})
{:ok, {:ok, "fourty two"}}
Similar to wrap/1
, but only returns a success result if the passed value is not nil
.
If it is, {:error, error}
is returned, where error
is either passed as a second
argument, or by default is :not_found
.
Note that generally Fey.Option.wrap_not_nil/1
is preferred, as it's more idiomatic.
However, if you're set on using Result
, this is available.
Examples
iex> Fey.Result.wrap_not_nil(42)
{:ok, 42}
iex> Fey.Result.wrap_not_nil(nil)
{:error, :not_found}
iex> Fey.Result.wrap_not_nil(nil, :number_missing)
{:error, :number_missing}