Current section
Files
Jump to
Current section
Files
lib/result.ex
defmodule Result do
@moduledoc false
@type ok(a) :: {:ok, a}
@type error(err) :: {:error, err}
@type t(a, err) :: ok(a) | error(err)
defmacro __using__(_opts) do
quote do
import Result.For
import Result.Pipe
end
end
@spec map({:ok, a}, (a -> b)) :: {:ok, b} when a: any, b: any
@spec map({:error, reason}, (any -> any)) :: {:error, reason} when reason: any
def map({:ok, value}, func) when is_function(func, 1), do: {:ok, func.(value)}
def map({:error, _} = err, _func), do: err
@spec map_err({:error, reason_a}, (reason_a -> reason_b)) :: {:error, reason_b}
when reason_a: any, reason_b: any
@spec map_err({:ok, a}, (any -> any)) :: {:ok, a} when a: any
def map_err({:error, reason}, func) when is_function(func, 1), do: {:error, func.(reason)}
def map_err({:ok, _v} = val, _func), do: val
@spec tap({:ok, a}, (a -> any)) :: {:ok, a} when a: any
@spec tap({:error, reason}, (any -> any)) :: {:error, reason} when reason: any
def tap({:ok, value}, func) when is_function(func, 1) do
func.(value)
{:ok, value}
end
def tap({:error, _} = err, _), do: err
@spec tap_err({:ok, a}, (any -> any)) :: {:ok, a} when a: any
@spec tap_err({:error, reason}, (reason -> any)) :: {:error, reason} when reason: any
def tap_err({:ok, _} = ok, _), do: ok
def tap_err({:error, reason} = err, func) when is_function(func, 1) do
func.(reason)
err
end
@spec flat_map({:ok, a} | {:error, reason}, (a -> {:ok, b} | {:error, reason})) ::
{:ok, b} | {:error, reason}
when a: any, b: any, reason: any
def flat_map({:ok, value}, func) when is_function(func, 1), do: func.(value)
def flat_map({:error, _} = err, _func), do: err
@spec fold({:ok, a}, (a -> b), (term -> term)) :: b when a: term, b: term
@spec fold({:error, a}, (term -> term), (a -> b)) :: b when a: term, b: term
def fold({:ok, value}, func, _) when is_function(func, 1), do: func.(value)
def fold({:error, reason}, _, func) when is_function(func, 1), do: func.(reason)
@spec or_else({:ok, a}, (term -> term)) :: {:ok, a} when a: term
@spec or_else({:error, a}, (a -> b)) :: b when a: term, b: t(term, term)
def or_else({:ok, value}, _), do: {:ok, value}
def or_else({:error, reason}, func) when is_function(func, 1), do: func.(reason)
@spec unwrap_or_else({:ok, a}, (term -> term)) :: a when a: term
@spec unwrap_or_else({:error, a}, (a -> b)) :: b when a: term, b: term
def unwrap_or_else({:ok, a}, _), do: a
def unwrap_or_else({:error, reason}, func) when is_function(func, 1), do: func.(reason)
@spec map_all([a], (a -> {:ok, b} | {:error, reason})) :: {:ok, [b]} | {:error, reason}
when a: any, b: any, reason: any
def map_all(list, func) when is_function(func, 1) do
result =
Enum.reduce_while(list, [], fn value, acc ->
case func.(value) do
{:ok, value} ->
{:cont, [value | acc]}
{:error, _} = error ->
{:halt, error}
end
end)
if is_list(result), do: {:ok, Enum.reverse(result)}, else: result
end
@spec check({:ok, a}, (a -> boolean), test_failure_reason) ::
{:ok, a} | {:error, test_failure_reason}
when a: any, test_failure_reason: any
@spec check({:error, reason}, (a -> boolean), test_failure_reason) :: {:error, reason}
when a: any, reason: any, test_failure_reason: any
def check({:ok, value}, func, reason) when is_function(func, 1) do
if func.(value) do
{:ok, value}
else
{:error, reason}
end
end
def check({:error, reason}, _func, _reason), do: {:error, reason}
@spec success?({:ok, a}) :: true when a: any
@spec success?({:error, reason}) :: false when reason: any
def success?({:ok, _value}), do: true
def success?({:error, _reason}), do: false
@spec failure?({:ok, a}) :: false when a: any
@spec failure?({:error, reason}) :: true when reason: any
def failure?({:ok, _value}), do: false
def failure?({:error, _reason}), do: true
@doc guard: true
@spec is_success(term()) :: Macro.t()
defguard is_success(result)
when is_tuple(result) and tuple_size(result) === 2 and elem(result, 0) === :ok
@doc guard: true
@spec is_failure(term()) :: Macro.t()
defguard is_failure(result)
when is_tuple(result) and tuple_size(result) === 2 and elem(result, 0) === :error
defmacro success(value) do
quote do
{:ok, unquote(value)}
end
end
defmacro failure(reason) do
quote do
{:error, unquote(reason)}
end
end
def wrap({:ok, _} = value), do: value
def wrap({:error, _} = err), do: err
def wrap(other), do: {:ok, other}
@spec from_nullable(any, any) :: {:ok, any} | {:error, any}
def from_nullable(value, reason \\ :value_required)
def from_nullable(nil, reason), do: {:error, reason}
def from_nullable(value, _reason), do: {:ok, value}
end