OkThen.Result (ok_then v1.1.0)
Functions to aid processing of tagged tuples in pipelines.
Examples
iex> 1
...> |> Result.from() # {:ok, 1}
...> |> Result.map(& &1 * 2) # {:ok, 2}
...> |> Result.then(& {:ok, &1 + 1}) # {:ok, 3}
...> |> Result.unwrap_or_else(0)
3
iex> "Oh no!"
...> |> Result.from_error() # {:error, "Oh no!"}
...> |> Result.map(& &1 * 2) # {:error, "Oh no!"}
...> |> Result.then(& {:ok, &1 + 1}) # {:error, "Oh no!"}
...> |> Result.unwrap_or_else(0)
0
iex> {:ok, 1}
...> |> Result.map(fn
...> 1 -> nil
...> x -> x * 2
...> end) # :none
...> |> Result.default(3) # {:ok, 3}
...> |> Result.unwrap_or_else(0)
3
iex> {:ok, 2}
...> |> Result.map(fn
...> 1 -> nil
...> x -> x * 2
...> end) # {:ok, 4}
...> |> Result.default(3) # {:ok, 4}
...> |> Result.unwrap_or_else(0)
4
iex> {:error, "Oh no!"}
...> |> Result.map(fn
...> 1 -> nil
...> x -> x * 2
...> end) # {:error, "Oh no!"}
...> |> Result.default(3) # {:error, "Oh no!"}
...> |> Result.unwrap_or_else(0)
0
iex> {:error, "Oh no!"}
...> |> Result.error_then(fn "Oh no!" -> :error end) # :error
...> |> Result.or_else(fn -> {:ok, 0} end) # {:ok, 0}
...> |> Result.unwrap!()
0
iex> {:ok, 1}
...> |> Result.error_then(fn "Oh no!" -> :error end) # {:ok, 1}
...> |> Result.or_else(fn -> {:ok, 0} end) # {:ok, 1}
...> |> Result.unwrap!()
1
Link to this section Summary
Guards
Returns true if result
is tagged :error
.
Returns true if result
is tagged :none
.
Returns true if result
is tagged :ok
.
Returns true if result
is tagged with the specified tag
atom.
Returns true if result
is a tagged tuple.
Functions (:ok)
If result
is tagged with :ok
, passes the wrapped value into the provided function (if
provided) and returns :none
.
If result
is tagged :ok
, passes the wrapped value into the provided function. If
func_or_value
returns a truthy value, result
is returned unchanged. Otherwise, returns
:none
. If func_or_value
is not a function, then it is used directly as the check value.
If result
is tagged :ok
, transforms the wrapped value by passing it into the provided
mapping function, and replacing it with the returned value. If func_or_value
is not a
function, then it is used directly as the new value.
If result
is not tagged with :ok
, passes the tag and wrapped value into the provided
function and returns the result. If the function has arity 1, then only the wrapped value is
passed in. If func_or_value
is not a function, then it is used directly as the new value.
If result
is tagged :ok
, replaces the tag with new_tag
, returning a new tagged tuple.
If result
is tagged with :ok
, passes the wrapped value into the provided function and
returns result
unchanged. The return value of the function is ignored.
If result
is tagged :ok
, passes the wrapped value into func_or_value
and returns the
result. If a function is not provided, the argument at the same position is returned as-is.
Same as unwrap_or_else/2
, except raises ArgumentError
if result
is not tagged :ok
.
Returns the wrapped value if result
is tagged :ok
. Otherwise, passes the tag and wrapped
value into the provided function and returns the result. If the function has arity 1, then only
the wrapped value is passed in. An arity-0 function is also accepted. If func_or_value
is not
a function, then it is used directly as the new value.
Functions (:error)
If result
is tagged with :error
, passes the wrapped value into the provided function (if
provided) and returns :none
.
If result
is tagged :error
, passes the wrapped value into the provided function. If
func_or_value
returns a truthy value, result
is returned unchanged. Otherwise, returns
:none
. If func_or_value
is not a function, then it is used directly as the check value.
If result
is tagged :error
, transforms the wrapped value by passing it into the provided
mapping function, and replacing it with the returned value. If func_or_value
is not a
function, then it is used directly as the new value.
If result
is not tagged with :error
, passes the tag and wrapped value into the provided
function and returns the result. If the function has arity 1, then only the wrapped value is
passed in. If func_or_value
is not a function, then it is used directly as the new value.
If result
is tagged :error
, replaces the tag with new_tag
, returning a new tagged tuple.
If result
is tagged with :error
, passes the wrapped value into the provided function and
returns result
unchanged. The return value of the function is ignored.
If result
is tagged :error
, passes the wrapped value into func_or_value
and returns the
result. If a function is not provided, the argument at the same position is returned as-is.
Same as error_unwrap_or_else/2
, except raises ArgumentError
if result
is not tagged
:error
.
Returns the wrapped value if result
is tagged :error
. Otherwise, passes the tag and wrapped
value into the provided function and returns the result. If the function has arity 1, then only
the wrapped value is passed in. An arity-0 function is also accepted. If func_or_value
is not
a function, then it is used directly as the new value.
Functions (:none)
If result
is tagged :none
, returns func_or_value
wrapped as an :ok
result. Otherwise,
returns result
. If func_or_value
is a function, the returned value is used as the new value.
Same as default/2
, except raises ArgumentError
if func_or_value
returns nil
.
If result
is tagged :none
, returns func_or_value
wrapped as a result with the given tag
.
Otherwise, returns result
. If func_or_value
is a function, the returned value is used as the
new value.
Same as default_as/3
, except raises ArgumentError
if func_or_value
returns nil
.
If result
is tagged :none
, returns func_or_value
wrapped as an :error
result. Otherwise,
returns result
. If func_or_value
is a function, the returned value is used as the new value.
Same as default_error/2
, except raises ArgumentError
if func_or_value
returns nil
.
If result
is tagged :none
, replaces the tag with new_tag
.
If result
is tagged :none
, calls func_or_value
and returns the result. If func_or_value
is not a function, then it is returned as-is.
Functions (any tag)
If result
is tagged with the specified tag
atom, passes the wrapped value into the provided
function (if provided) and returns :none
.
If result
is tagged with the specified tag
atom, passes the wrapped value into the provided
function. If func_or_value
returns a truthy value, result
is returned unchanged. Otherwise,
returns :none
. If func_or_value
is not a function, then it is used directly as the check
value.
If result
is tagged with the specified tag
atom, transforms the wrapped value by passing it
into the provided mapping function, and replacing it with the returned value. If a function is
not provided, the argument at the same position is used as the new value.
If result
is not tagged with the specified tag
atom, passes the tag and wrapped value into
the provided function and returns the result. If the function has arity 1, then only the wrapped
value is passed in. An arity-0 function is also accepted. If func_or_value
is not a function,
then it is used directly as the new value.
If result
is tagged with the specified tag
atom, replaces the tag with new_tag
, returning
a new tagged tuple.
If result
is tagged with the specified tag
atom, passes the wrapped value into the provided
function and returns result
unchanged. The return value of the function is ignored.
If result
is tagged with the specified tag
atom, passes the wrapped value into the provided
function and returns the result. If func_or_value
is not a function, then it is returned
as-is.
Same as tagged_unwrap_or_else/3
, except raises ArgumentError
if result
is not tagged with
the specified tag
atom.
Returns the wrapped value if result
is tagged with the specified tag
atom. Otherwise, passes
the tag and wrapped value into the provided function and returns the result. If the function
has arity 1, then only the wrapped value is passed in. An arity-0 function is also accepted. If
func_or_value
is not a function, then it is used directly as the new value.
Functions
Converts value
into a maybe(v)
result: {:ok, value} | :none
Same as from/1
, except raises ArgumentError
if value
is nil
.
Converts value
into a maybe_is(tag)
result: {atom(), any()} | :none
Same as from_as/2
, except raises ArgumentError
if value
is nil
.
Converts value
into a maybe_error(e)
result: {:error, value} | :none
Same as from_error/1
, except raises ArgumentError
if value
is nil
.
Converts result
from a variety of accepted result-like terms into an atom or a two-element
tagged tuple.
Same as normalize/1
, except raises ArgumentError
if value
is untagged.
Link to this section Types
error(t)
Specs
error(t) :: {:error, t}
maybe()
Specs
maybe() :: maybe_is(:ok)
maybe(t)
Specs
maybe(t) :: maybe_is(:ok, t)
maybe(t, e)
Specs
maybe_error()
Specs
maybe_error() :: maybe_is(:error)
maybe_error(e)
Specs
maybe_error(e) :: maybe_is(:error, e)
maybe_is(t)
Specs
maybe_is(t) :: t | :none
maybe_is(t, v)
Specs
maybe_is(t, v) :: {t, v} | :none
ok(t)
Specs
ok(t) :: {:ok, t}
ok_or(e)
Specs
ok_or(e) :: :ok | error(e)
ok_or(t, e)
Specs
result_input()
Specs
tagged()
Specs
Link to this section Guards
Returns true if result
is tagged :error
.
Equivalent to is_tagged(value, :error)
. See is_tagged/2
.
Examples
iex> Result.is_error(:error)
true
iex> Result.is_error({:error, "hello"})
true
iex> Result.is_error({:ok, "hello"})
false
Returns true if result
is tagged :none
.
Equivalent to is_tagged(value, :none)
. See is_tagged/2
.
Examples
iex> Result.is_none(:none)
true
iex> Result.is_none({:ok, "hello"})
false
iex> Result.is_none({:error, "hello"})
false
Returns true if result
is tagged :ok
.
Equivalent to is_tagged(value, :ok)
. See is_tagged/2
.
Examples
iex> Result.is_ok(:ok)
true
iex> Result.is_ok({:ok, "hello"})
true
iex> Result.is_ok({:error, "hello"})
false
Returns true if result
is tagged with the specified tag
atom.
Examples
iex> Result.is_tagged(:ok, :ok)
true
iex> Result.is_tagged({:ok, "hello"}, :ok)
true
iex> Result.is_tagged({:error, "hello"}, :ok)
false
iex> Result.is_tagged({:ok, 1, 2}, :ok)
true
iex> Result.is_tagged({:ok, {1, 2}}, :ok)
true
iex> Result.is_tagged({:strange, "hello"}, :strange)
true
iex> hello = fn -> "hello" end
...> hello.() |> Result.is_tagged(:ok)
false
Returns true if result
is a tagged tuple.
Examples
iex> Result.is_tagged_tuple(:ok)
true
iex> Result.is_tagged_tuple({:ok, "hello"})
true
iex> Result.is_tagged_tuple({:error, "hello"})
true
iex> Result.is_tagged_tuple({:ok, 1, 2})
true
iex> Result.is_tagged_tuple({:ok, {1, 2}})
true
iex> Result.is_tagged_tuple({:strange, "hello"})
true
iex> Result.is_tagged_tuple({"ok", "hello"})
false
iex> func = fn -> "hello" end
...> func.() |> Result.is_tagged_tuple()
false
iex> func = fn -> nil end
...> func.() |> Result.is_tagged_tuple()
false
iex> Result.is_tagged_tuple({nil, "hello"})
false
Link to this section Functions (:ok)
consume(result, function \\ &(&1))
Specs
consume(result_input(), (any() -> any())) :: result_input() | :none
If result
is tagged with :ok
, passes the wrapped value into the provided function (if
provided) and returns :none
.
If result
is not tagged with :ok
, result
is returned as-is.
Equivalent to tagged_consume(result, :ok, func_or_value)
. See tagged_consume/3
.
Examples
iex> :ok |> Result.consume()
:none
iex> :ok |> Result.consume(fn -> "hello" end)
:none
iex> :ok |> Result.consume(fn {} -> "hello" end)
:none
iex> {:ok, 1} |> Result.consume(fn 1 -> "hello" end)
:none
iex> {:ok, 1, 2} |> Result.consume(fn 1, 2 -> "hello" end)
** (ArgumentError) Value-mapping function must have arity between 0 and 1.
iex> {:ok, 1, 2} |> Result.consume(fn {1, 2} -> "hello" end)
:none
iex> :error |> Result.consume(fn {} -> "hello" end)
:error
iex> {:error, 1} |> Result.consume(fn 1 -> "hello" end)
{:error, 1}
iex> "bare value" |> Result.consume()
"bare value"
filter(result, func_or_value)
Specs
filter(result_input(), OkThen.Result.Private.func_or_value(as_boolean(any()))) :: result_input()
If result
is tagged :ok
, passes the wrapped value into the provided function. If
func_or_value
returns a truthy value, result
is returned unchanged. Otherwise, returns
:none
. If func_or_value
is not a function, then it is used directly as the check value.
Equivalent to tagged_filter(result, :ok, func_or_value)
. See tagged_filter/3
.
Examples
iex> {:ok, "hello"} |> Result.filter(&String.length(&1) == 5)
{:ok, "hello"}
iex> {:ok, "hello"} |> Result.filter(&String.length(&1) == 0)
:none
iex> {:ok, "hello"} |> Result.filter(fn -> true end)
{:ok, "hello"}
iex> {:ok, "hello"} |> Result.filter(fn -> false end)
:none
iex> {:ok, "hello"} |> Result.filter(true)
{:ok, "hello"}
iex> {:ok, "hello"} |> Result.filter(false)
:none
iex> :some |> Result.filter(&String.length(&1) == 0)
:some
iex> :error |> Result.filter(&String.length(&1) == 0)
:error
iex> nil |> Result.filter(&String.length(&1) == 0)
nil
map(result, func_or_value)
Specs
map(t, OkThen.Result.Private.func_or_value(out)) :: t | :ok | ok(out) when t: result_input(), out: any()
If result
is tagged :ok
, transforms the wrapped value by passing it into the provided
mapping function, and replacing it with the returned value. If func_or_value
is not a
function, then it is used directly as the new value.
If the new value would be nil
, then :none
is returned as the result instead. Consider piping
into |> none_then({:ok, nil})
if you really want {:ok, nil}
. See none_then/2
.
If result
is not tagged :ok
, result
is returned as-is.
Equivalent to tagged_map(result, :ok, func_or_value)
. See tagged_map/3
.
Examples
iex> :ok |> Result.map("hello")
{:ok, "hello"}
iex> {:ok, 1} |> Result.map("hello")
{:ok, "hello"}
iex> {:ok, 1} |> Result.map(nil)
:none
iex> :none |> Result.map("hello")
:none
iex> :ok |> Result.map(fn {} -> "hello" end)
{:ok, "hello"}
iex> {:ok, 1} |> Result.map(fn 1 -> "hello" end)
{:ok, "hello"}
iex> {:ok, 1, 2} |> Result.map(fn {1, 2} -> "hello" end)
{:ok, "hello"}
iex> {:ok, 1, 2} |> Result.map(fn 1, 2 -> "hello" end)
** (ArgumentError) Value-mapping function must have arity between 0 and 1.
iex> {:ok, 1, 2} |> Result.map(fn {1, 2} -> {} end)
:ok
iex> :error |> Result.map(fn _ -> "hello" end)
:error
iex> {:error, 1} |> Result.map(fn _ -> "hello" end)
{:error, 1}
iex> {:error, 1, 2} |> Result.map(fn _ -> "hello" end)
{:error, 1, 2}
iex> :none |> Result.map(fn _ -> "hello" end)
:none
iex> :something_else |> Result.map(fn _ -> "hello" end)
:something_else
iex> "bare value" |> Result.map(fn _ -> "hello" end)
"bare value"
iex> "bare value" |> Result.map("hello")
"bare value"
or_else(result, func_or_value)
Specs
or_else(result_input(), OkThen.Result.Private.func_or_value(atom(), out)) :: out when out: any()
If result
is not tagged with :ok
, passes the tag and wrapped value into the provided
function and returns the result. If the function has arity 1, then only the wrapped value is
passed in. If func_or_value
is not a function, then it is used directly as the new value.
If result
is tagged with :ok
, result
is returned as-is.
Use this function in a pipeline to branch the unhappy path into another function, or as a kind
of case
expression to handle multiple types of result without the boilerplate of copying
through a successful result.
Be aware that no attempt is made to ensure the return value from the function is a tagged tuple.
However, all functions are tolerant of untagged results, and on input will interpret them as an
{:untagged, value}
tuple.
Equivalent to tagged_or_else(result, :ok, func_or_value)
. See tagged_or_else/3
.
Examples
iex> :error
...> |> Result.or_else(fn
...> :error, {} -> {:ok, "hello"}
...> end)
{:ok, "hello"}
iex> {:error, 1}
...> |> Result.or_else(fn
...> :error, 1 -> {:ok, "hello"}
...> end)
{:ok, "hello"}
iex> {:error, 1, 2}
...> |> Result.or_else(fn
...> :error, {1, 2} -> {:ok, "matched error"}
...> :none, {} -> {:ok, "matched none"}
...> end)
{:ok, "matched error"}
iex> :none
...> |> Result.or_else(fn
...> :error, {1, 2} -> {:ok, "matched error"}
...> :none, {} -> {:ok, "matched none"}
...> end)
{:ok, "matched none"}
iex> {:ok, "just ok"}
...> |> Result.or_else(fn
...> :error, {1, 2} -> {:error, "matched error"}
...> :none, {} -> {:ok, "matched none"}
...> end)
{:ok, "just ok"}
iex> {:error, 1, 2}
...> |> Result.or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched two terms"}
iex> {:error, 1}
...> |> Result.or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched one term"}
iex> :error
...> |> Result.or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched no terms"}
iex> :none
...> |> Result.or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched no terms"}
iex> :error |> Result.or_else({:ok, "hello"})
{:ok, "hello"}
iex> {:error, 1} |> Result.or_else({:ok, "hello"})
{:ok, "hello"}
iex> {:error, 1} |> Result.or_else("bare value")
"bare value"
iex> "bare value" |> Result.or_else(fn _ -> :none end)
:none
iex> "bare value" |> Result.or_else(fn
...> :untagged, "bare value" -> :none
...> end)
:none
retag(result, new_tag)
Specs
retag(result_input(), new_tag) :: new_tag | {new_tag, any()} when new_tag: atom()
If result
is tagged :ok
, replaces the tag with new_tag
, returning a new tagged tuple.
Equivalent to tagged_retag(result, :ok, new_tag)
. See tagged_retag/3
.
Examples
iex> :ok |> Result.retag(:none)
:none
iex> {:ok, "hello"} |> Result.retag(:error)
{:error, "hello"}
iex> {:ok, 1, 2} |> Result.retag(:error)
{:error, {1, 2}}
iex> {:error, 1, 2} |> Result.retag(:ok)
{:error, 1, 2}
iex> :ok |> Result.retag("string")
** (ArgumentError) Expected atom as new tag, got: "string".
iex> "bare value" |> Result.error_retag(:error)
"bare value"
tap(result, function)
Specs
tap(result_input(), OkThen.Result.Private.func_or_value(any())) :: result_input()
If result
is tagged with :ok
, passes the wrapped value into the provided function and
returns result
unchanged. The return value of the function is ignored.
If result
is not tagged with :ok
, the provided function is not called.
Equivalent to tagged_tap(result, :ok, function)
. See tagged_tap/3
.
Examples
iex> capture_io(fn ->
...> assert :ok |> Result.tap(fn -> IO.write("hello") end) == :ok
...> end)
"hello"
iex> capture_io(fn ->
...> input = {:ok, "in"}
...> assert input |> Result.tap(fn "in" -> IO.write("hello") end) == input
...> end)
"hello"
iex> capture_io(fn ->
...> input = {:ok, "one", "two"}
...> function = fn {"one", "two"} -> IO.write("hello") end
...> assert input |> Result.tap(function) == input
...> end)
"hello"
iex> capture_io(fn ->
...> input = {:error, "reason"}
...> assert input |> Result.tap(fn -> IO.write("hello") end) == input
...> end)
""
then(result, func_or_value)
Specs
then(result_input(), OkThen.Result.Private.func_or_value(out)) :: out when out: any()
If result
is tagged :ok
, passes the wrapped value into func_or_value
and returns the
result. If a function is not provided, the argument at the same position is returned as-is.
If result
is not tagged with the specified tag
atom, result
is returned as-is.
Use this function to pipe results into functions that return tagged tuples.
Be aware that no attempt is made to ensure the return value from the function is a tagged tuple.
However, all functions are tolerant of untagged results, and on input will interpret them as an
{:untagged, value}
tuple.
Equivalent to tagged_then(result, :ok, func_or_value)
. See tagged_then/3
.
Examples
iex> :ok |> Result.then({:ok, "hello"})
{:ok, "hello"}
iex> {:ok, 1} |> Result.then({:ok, "hello"})
{:ok, "hello"}
iex> :none |> Result.then({:ok, "hello"})
:none
iex> :ok |> Result.then(fn {} -> {:ok, "hello"} end)
{:ok, "hello"}
iex> {:ok, 1} |> Result.then(fn 1 -> {:ok, "hello"} end)
{:ok, "hello"}
iex> {:ok, 1, 2} |> Result.then(fn {1, 2} -> {:ok, "hello"} end)
{:ok, "hello"}
iex> {:ok, 1, 2} |> Result.then(fn 1, 2 -> {:ok, "hello"} end)
** (ArgumentError) Value-mapping function must have arity between 0 and 1.
iex> {:ok, 1, 2} |> Result.then(fn {1, 2} -> :ok end)
:ok
iex> :error |> Result.then(fn _ -> {:ok, "hello"} end)
:error
iex> {:error, 1} |> Result.then(fn _ -> {:ok, "hello"} end)
{:error, 1}
iex> {:error, 1, 2} |> Result.then(fn _ -> {:ok, "hello"} end)
{:error, 1, 2}
iex> :none |> Result.then(fn _ -> {:ok, "hello"} end)
:none
iex> :something_else |> Result.then(fn _ -> {:ok, "hello"} end)
:something_else
iex> "bare value" |> Result.then({:ok, "hello"})
"bare value"
iex> "bare value" |> Result.then(fn _ -> {:ok, "hello"} end)
"bare value"
unwrap!(result)
Specs
unwrap!(result_input()) :: any()
Same as unwrap_or_else/2
, except raises ArgumentError
if result
is not tagged :ok
.
Examples
iex> {:ok, "hello"} |> Result.unwrap!()
"hello"
iex> :ok |> Result.unwrap!()
{}
iex> :error |> Result.unwrap!()
** (ArgumentError) Result is not tagged ok: :error.
iex> {:error, "hello"} |> Result.unwrap!()
** (ArgumentError) Result is not tagged ok: {:error, "hello"}.
iex> :none |> Result.unwrap!()
** (ArgumentError) Result is not tagged ok: :none.
iex> "hello" |> Result.unwrap!()
** (ArgumentError) Result is not tagged ok: "hello".
unwrap_or_else(result, func_or_value)
Specs
unwrap_or_else(result_input(), OkThen.Result.Private.func_or_value(any())) :: any()
Returns the wrapped value if result
is tagged :ok
. Otherwise, passes the tag and wrapped
value into the provided function and returns the result. If the function has arity 1, then only
the wrapped value is passed in. An arity-0 function is also accepted. If func_or_value
is not
a function, then it is used directly as the new value.
See also tagged_or_else/3
.
Equivalent to tagged_unwrap_or_else(result, :ok, default)
. See tagged_unwrap_or_else/3
.
Examples
iex> {:ok, "hello"} |> Result.unwrap_or_else("default")
"hello"
iex> :ok |> Result.unwrap_or_else("default")
{}
iex> :error |> Result.unwrap_or_else("default")
"default"
iex> {:error, "hello"} |> Result.unwrap_or_else("default")
"default"
iex> {:error, "hello"}
...> |> Result.unwrap_or_else(fn
...> :error, "hello" -> "default"
...> end)
"default"
iex> {:error, "hello"}
...> |> Result.unwrap_or_else(fn
...> "hello" -> "default"
...> end)
"default"
iex> {:error, "hello"} |> Result.unwrap_or_else(fn -> "default" end)
"default"
iex> :none |> Result.unwrap_or_else("default")
"default"
iex> "hello" |> Result.unwrap_or_else("default")
"default"
Link to this section Functions (:error)
error_consume(result, function \\ &(&1))
Specs
error_consume(result_input(), (any() -> any())) :: result_input() | :none
If result
is tagged with :error
, passes the wrapped value into the provided function (if
provided) and returns :none
.
If result
is not tagged with :error
, result
is returned as-is.
Equivalent to tagged_consume(result, :error, func_or_value)
. See tagged_consume/3
.
Examples
iex> :error |> Result.error_consume()
:none
iex> :error |> Result.error_consume(fn -> "hello" end)
:none
iex> :error |> Result.error_consume(fn {} -> "hello" end)
:none
iex> {:error, 1} |> Result.error_consume(fn 1 -> "hello" end)
:none
iex> {:error, 1, 2} |> Result.error_consume(fn 1, 2 -> "hello" end)
** (ArgumentError) Value-mapping function must have arity between 0 and 1.
iex> {:error, 1, 2} |> Result.error_consume(fn {1, 2} -> "hello" end)
:none
iex> :ok |> Result.error_consume(fn {} -> "hello" end)
:ok
iex> {:ok, 1} |> Result.error_consume(fn 1 -> "hello" end)
{:ok, 1}
iex> "bare value" |> Result.error_consume()
"bare value"
error_filter(result, func_or_value)
Specs
error_filter( result_input(), OkThen.Result.Private.func_or_value(as_boolean(any())) ) :: result_input()
If result
is tagged :error
, passes the wrapped value into the provided function. If
func_or_value
returns a truthy value, result
is returned unchanged. Otherwise, returns
:none
. If func_or_value
is not a function, then it is used directly as the check value.
Equivalent to tagged_filter(result, :error, func_or_value)
. See tagged_filter/3
.
Examples
iex> {:error, "hello"} |> Result.error_filter(&String.length(&1) == 5)
{:error, "hello"}
iex> {:error, "hello"} |> Result.error_filter(&String.length(&1) == 0)
:none
iex> {:error, "hello"} |> Result.error_filter(fn -> true end)
{:error, "hello"}
iex> {:error, "hello"} |> Result.error_filter(fn -> false end)
:none
iex> {:error, "hello"} |> Result.error_filter(true)
{:error, "hello"}
iex> {:error, "hello"} |> Result.error_filter(false)
:none
iex> :some |> Result.error_filter(&String.length(&1) == 0)
:some
iex> :ok |> Result.error_filter(&String.length(&1) == 0)
:ok
iex> nil |> Result.error_filter(&String.length(&1) == 0)
nil
error_map(result, func_or_value)
Specs
error_map(t, OkThen.Result.Private.func_or_value(out)) :: t | :error | error(out) when t: result_input(), out: any()
If result
is tagged :error
, transforms the wrapped value by passing it into the provided
mapping function, and replacing it with the returned value. If func_or_value
is not a
function, then it is used directly as the new value.
If the new value would be nil
, then :none
is returned as the result instead. Consider piping
into |> none_then({:error, nil})
if you really want {:error, nil}
. See none_then/2
.
If result
is not tagged :error
, result
is returned as-is.
Equivalent to tagged_map(result, :error, func_or_value)
. See tagged_map/3
.
Examples
iex> :error |> Result.error_map("hello")
{:error, "hello"}
iex> {:error, 1} |> Result.error_map("hello")
{:error, "hello"}
iex> {:error, 1} |> Result.error_map(nil)
:none
iex> :none |> Result.error_map("hello")
:none
iex> :error |> Result.error_map(fn {} -> "hello" end)
{:error, "hello"}
iex> {:error, 1} |> Result.error_map(fn 1 -> "hello" end)
{:error, "hello"}
iex> {:error, 1, 2} |> Result.error_map(fn {1, 2} -> "hello" end)
{:error, "hello"}
iex> {:error, 1, 2} |> Result.error_map(fn 1, 2 -> "hello" end)
** (ArgumentError) Value-mapping function must have arity between 0 and 1.
iex> {:error, 1, 2} |> Result.error_map(fn {1, 2} -> {} end)
:error
iex> :ok |> Result.error_map(fn _ -> "hello" end)
:ok
iex> {:ok, 1} |> Result.error_map(fn _ -> "hello" end)
{:ok, 1}
iex> {:ok, 1, 2} |> Result.error_map(fn _ -> "hello" end)
{:ok, 1, 2}
iex> :none |> Result.error_map(fn _ -> "hello" end)
:none
iex> :something_else |> Result.error_map(fn _ -> "hello" end)
:something_else
iex> "bare value" |> Result.error_map(fn _ -> "hello" end)
"bare value"
iex> "bare value" |> Result.error_map("hello")
"bare value"
error_or_else(result, func_or_value)
Specs
error_or_else(result_input(), OkThen.Result.Private.func_or_value(atom(), out)) :: out when out: any()
If result
is not tagged with :error
, passes the tag and wrapped value into the provided
function and returns the result. If the function has arity 1, then only the wrapped value is
passed in. If func_or_value
is not a function, then it is used directly as the new value.
If result
is tagged with :error
, result
is returned as-is.
Use this function in a pipeline to branch the happy path into another function, or as a kind of
case
expression to handle multiple types of result without the boilerplate of copying through
an error result.
Be aware that no attempt is made to ensure the return value from the function is a tagged tuple.
However, all functions are tolerant of untagged results, and on input will interpret them as an
{:untagged, value}
tuple.
Equivalent to tagged_or_else(result, :error, func_or_value)
. See tagged_or_else/3
.
Examples
iex> :ok
...> |> Result.error_or_else(fn
...> :ok, {} -> {:ok, "hello"}
...> end)
{:ok, "hello"}
iex> {:ok, 1}
...> |> Result.error_or_else(fn
...> :ok, 1 -> {:ok, "hello"}
...> end)
{:ok, "hello"}
iex> {:ok, 1, 2}
...> |> Result.error_or_else(fn
...> :ok, {1, 2} -> {:ok, "matched ok"}
...> :none, {} -> {:ok, "matched none"}
...> end)
{:ok, "matched ok"}
iex> :none
...> |> Result.error_or_else(fn
...> :ok, {1, 2} -> {:ok, "matched ok"}
...> :none, {} -> {:ok, "matched none"}
...> end)
{:ok, "matched none"}
iex> {:error, "just error"}
...> |> Result.error_or_else(fn
...> :ok, {1, 2} -> {:ok, "matched ok"}
...> :none, {} -> {:ok, "matched none"}
...> end)
{:error, "just error"}
iex> {:ok, 1, 2}
...> |> Result.error_or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched two terms"}
iex> {:ok, 1}
...> |> Result.error_or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched one term"}
iex> :ok
...> |> Result.error_or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched no terms"}
iex> :none
...> |> Result.error_or_else(fn
...> {1, 2} -> {:ok, "matched two terms"}
...> 1 -> {:ok, "matched one term"}
...> {} -> {:ok, "matched no terms"}
...> end)
{:ok, "matched no terms"}
iex> :ok |> Result.error_or_else({:ok, "hello"})
{:ok, "hello"}
iex> {:ok, 1} |> Result.error_or_else({:ok, "hello"})
{:ok, "hello"}
iex> {:ok, 1} |> Result.error_or_else("bare value")
"bare value"
iex> "bare value" |> Result.error_or_else(fn _ -> :none end)
:none
iex> "bare value" |> Result.error_or_else(fn
...> :untagged, "bare value" -> :none
...> end)
:none
error_retag(result, new_tag)
Specs
error_retag(result_input(), new_tag) :: new_tag | {new_tag, any()} when new_tag: atom()
If result
is tagged :error
, replaces the tag with new_tag
, returning a new tagged tuple.
Equivalent to tagged_retag(result, :error, new_tag)
. See tagged_retag/3
.
Examples
iex> :error |> Result.error_retag(:none)
:none
iex> {:error, "hello"} |> Result.error_retag(:ok)
{:ok, "hello"}
iex> {:error, 1, 2} |> Result.error_retag(:ok)
{:ok, {1, 2}}
iex> {:ok, 1, 2} |> Result.error_retag(:error)
{:ok, 1, 2}
iex> :error |> Result.error_retag("string")
** (ArgumentError) Expected atom as new tag, got: "string".
iex> "bare value" |> Result.error_retag(:ok)
"bare value"
error_tap(result, function)
Specs
error_tap(result_input(), OkThen.Result.Private.func_or_value(any())) :: result_input()
If result
is tagged with :error
, passes the wrapped value into the provided function and
returns result
unchanged. The return value of the function is ignored.
If result
is not tagged with :error
, the provided function is not called.
Equivalent to tagged_tap(result, :error, function)
. See tagged_tap/3
.
Examples
iex> capture_io(fn ->
...> assert :error |> Result.error_tap(fn -> IO.write("hello") end) == :error
...> end)
"hello"
iex> capture_io(fn ->
...> input = {:error, "reason"}
...> assert input |> Result.error_tap(fn "reason" -> IO.write("hello") end) == input
...> end)
"hello"
iex> capture_io(fn ->
...> input = {:error, "one", "two"}
...> function = fn {"one", "two"} -> IO.write("hello") end
...> assert input |> Result.error_tap(function) == input
...> end)
"hello"
iex> capture_io(fn ->
...> input = {:ok, "in"}
...> assert input |> Result.error_tap(fn -> IO.write("hello") end) == input
...> end)
""
error_then(result, func_or_value)
Specs
error_then(result_input(), OkThen.Result.Private.func_or_value(out)) :: out when out: any()
If result
is tagged :error
, passes the wrapped value into func_or_value
and returns the
result. If a function is not provided, the argument at the same position is returned as-is.
If result
is not tagged with the specified tag
atom, result
is returned as-is.
Use this function to pipe results into functions that return tagged tuples.
Be aware that no attempt is made to ensure the return value from the function is a tagged tuple.
However, all functions are tolerant of untagged results, and on input will interpret them as an
{:untagged, value}
tuple.
Equivalent to tagged_then(result, :error, func_or_value)
. See tagged_then/3
.
Examples
iex> :error |> Result.error_then({:ok, "hello"})
{:ok, "hello"}
iex> {:error, 1} |> Result.error_then({:ok, "hello"})
{:ok, "hello"}
iex> :none |> Result.error_then({:ok, "hello"})
:none
iex> :error |> Result.error_then(fn -> {:ok, "hello"} end)
{:ok, "hello"}
iex> :error |> Result.error_then(fn {} -> {:ok, "hello"} end)
{:ok, "hello"}
iex> {:error, 1} |> Result.error_then(fn 1 -> {:ok, "hello"} end)
{:ok, "hello"}
iex> {:error, 1, 2} |> Result.error_then(fn {1, 2} -> {:ok, "hello"} end)
{:ok, "hello"}
iex> {:error, 1, 2} |> Result.error_then(fn 1, 2 -> {:ok, "hello"} end)
** (ArgumentError) Value-mapping function must have arity between 0 and 1.
iex> {:error, 1, 2} |> Result.error_then(fn {1, 2} -> :ok end)
:ok
iex> :ok |> Result.error_then(fn _ -> {:ok, "hello"} end)
:ok
iex> {:ok, 1} |> Result.error_then(fn _ -> {:ok, "hello"} end)
{:ok, 1}
iex> {:ok, 1, 2} |> Result.error_then(fn _ -> {:ok, "hello"} end)
{:ok, 1, 2}
iex> :none |> Result.error_then(fn _ -> {:ok, "hello"} end)
:none
iex> :something_else |> Result.error_then(fn _ -> {:ok, "hello"} end)
:something_else
iex> "bare value" |> Result.error_then({:ok, "hello"})
"bare value"
iex> "bare value" |> Result.error_then(fn _ -> {:ok, "hello"} end)
"bare value"
error_unwrap!(result)
Specs
error_unwrap!(result_input()) :: any()
Same as error_unwrap_or_else/2
, except raises ArgumentError
if result
is not tagged
:error
.
Examples
iex> {:error, "hello"} |> Result.error_unwrap!()
"hello"
iex> :error |> Result.error_unwrap!()
{}
iex> :ok |> Result.error_unwrap!()
** (ArgumentError) Result is not tagged error: :ok.
iex> {:ok, "hello"} |> Result.error_unwrap!()
** (ArgumentError) Result is not tagged error: {:ok, "hello"}.
iex> :none |> Result.error_unwrap!()
** (ArgumentError) Result is not tagged error: :none.
iex> "hello" |> Result.error_unwrap!()
** (ArgumentError) Result is not tagged error: "hello".
error_unwrap_or_else(result, func_or_value)
Specs
error_unwrap_or_else(result_input(), OkThen.Result.Private.func_or_value(any())) :: any()
Returns the wrapped value if result
is tagged :error
. Otherwise, passes the tag and wrapped
value into the provided function and returns the result. If the function has arity 1, then only
the wrapped value is passed in. An arity-0 function is also accepted. If func_or_value
is not
a function, then it is used directly as the new value.
See also tagged_or_else/3
.
Equivalent to tagged_unwrap_or_else(result, :error, default)
. See tagged_unwrap_or_else/3
.
Examples
iex> {:error, "hello"} |> Result.error_unwrap_or_else("default")
"hello"
iex> :error |> Result.error_unwrap_or_else("default")
{}
iex> :ok |> Result.error_unwrap_or_else("default")
"default"
iex> {:ok, "hello"} |> Result.error_unwrap_or_else("default")
"default"
iex> {:ok, "hello"}
...> |> Result.error_unwrap_or_else(fn
...> :ok, "hello" -> "default"
...> end)
"default"
iex> {:ok, "hello"}
...> |> Result.error_unwrap_or_else(fn
...> "hello" -> "default"
...> end)
"default"
iex> {:error, "hello"} |> Result.tagged_unwrap_or_else(:ok, fn -> "default" end)
"default"
iex> :none |> Result.error_unwrap_or_else("default")
"default"
iex> "hello" |> Result.error_unwrap_or_else("default")
"default"
Link to this section Functions (:none)
default(result, func_or_value)
Specs
default(input, (() -> out) | out) :: input | :ok | ok(out) when input: result_input(), out: any()
If result
is tagged :none
, returns func_or_value
wrapped as an :ok
result. Otherwise,
returns result
. If func_or_value
is a function, the returned value is used as the new value.
If the new value is nil
, then the result will remain :none
. Consider using none_then/2
if
you don't want this behaviour.
If result
is not tagged :none
, result
is returned as-is.
Equivalent to default_as(result, :ok, func_or_value)
. See default_as/3
.
Examples
iex> :none |> Result.default("hello")
{:ok, "hello"}
iex> :none |> Result.default({})
:ok
iex> :none |> Result.default(nil)
:none
iex> :none |> Result.default(fn -> 1 end)
{:ok, 1}
iex> :none |> Result.default(fn {} -> 1 end)
{:ok, 1}
iex> {:none, 1} |> Result.default(& &1)
{:ok, 1}
iex> :ok |> Result.default("hello")
:ok
iex> {:ok, 1} |> Result.default("hello")
{:ok, 1}
iex> {:ok, 1, 2} |> Result.default("hello")
{:ok, 1, 2}
iex> {:anything, 1} |> Result.default("hello")
{:anything, 1}
iex> "bare value" |> Result.default("hello")
"bare value"
default!(result, func_or_value)
Same as default/2
, except raises ArgumentError
if func_or_value
returns nil
.
Examples
iex> :none |> Result.default!("hello")
{:ok, "hello"}
iex> :none |> Result.default!({})
:ok
iex> :none |> Result.default!(nil)
** (ArgumentError) Value is nil.
iex> :none |> Result.default!(fn -> nil end)
** (ArgumentError) Value is nil.
default_as(result, tag, func_or_value)
Specs
default_as(input, tag, (() -> out) | out) :: input | tag | {tag, out} when input: result_input(), tag: atom(), out: any()
If result
is tagged :none
, returns func_or_value
wrapped as a result with the given tag
.
Otherwise, returns result
. If func_or_value
is a function, the returned value is used as the
new value.
If the new value is nil
, then the result will remain :none
. Consider using none_then/2
if
you don't want this behaviour.
If result
is not tagged :none
, result
is returned as-is.
Examples
iex> :none |> Result.default_as(:ok, "hello")
{:ok, "hello"}
iex> :none |> Result.default_as(:error, {})
:error
iex> :none |> Result.default_as(:something, nil)
:none
iex> :none |> Result.default_as(:ok, fn -> 1 end)
{:ok, 1}
iex> :none |> Result.default_as(:ok, fn {} -> 1 end)
{:ok, 1}
iex> {:none, 1} |> Result.default_as(:ok, & &1)
{:ok, 1}
iex> :ok |> Result.default_as(:ok, "hello")
:ok
iex> {:ok, 1} |> Result.default_as(:ok, "hello")
{:ok, 1}
iex> {:ok, 1, 2} |> Result.default_as(:ok, "hello")
{:ok, 1, 2}
iex> {:anything, 1} |> Result.default_as(:ok, "hello")
{:anything, 1}
iex> "bare value" |> Result.default_as(:ok, "hello")
"bare value"
default_as!(result, tag, func_or_value)
Specs
default_as!(input, tag, (() -> out) | out) :: input | tag | {tag, out} when input: result_input(), tag: atom(), out: any()
Same as default_as/3
, except raises ArgumentError
if func_or_value
returns nil
.
Examples
iex> :none |> Result.default_as!(:ok, "hello")
{:ok, "hello"}
iex> :none |> Result.default_as!(:ok, {})
:ok
iex> :none |> Result.default_as!(:ok, nil)
** (ArgumentError) Value is nil.
iex> :none |> Result.default_as!(:ok, fn -> nil end)
** (ArgumentError) Value is nil.
default_error(result, func_or_value)
Specs
default_error(input, (() -> out) | out) :: input | :error | error(out) when input: result_input(), out: any()
If result
is tagged :none
, returns func_or_value
wrapped as an :error
result. Otherwise,
returns result
. If func_or_value
is a function, the returned value is used as the new value.
If the new value is nil
, then the result will remain :none
. Consider using none_then/2
if
you don't want this behaviour.
If result
is not tagged :none
, result
is returned as-is.
Equivalent to default_as(result, :error, func_or_value)
. See default_as/3
.
Examples
iex> :none |> Result.default_error("hello")
{:error, "hello"}
iex> :none |> Result.default_error({})
:error
iex> :none |> Result.default_error(nil)
:none
iex> :none |> Result.default_error(fn -> 1 end)
{:error, 1}
iex> :none |> Result.default_error(fn {} -> 1 end)
{:error, 1}
iex> {:none, 1} |> Result.default_error(& &1)
{:error, 1}
iex> :error |> Result.default_error("hello")
:error
iex> {:error, 1} |> Result.default_error("hello")
{:error, 1}
iex> {:error, 1, 2} |> Result.default_error("hello")
{:error, 1, 2}
iex> {:anything, 1} |> Result.default_error("hello")
{:anything, 1}
iex> "bare value" |> Result.default_error("hello")
"bare value"
default_error!(result, func_or_value)
Same as default_error/2
, except raises ArgumentError
if func_or_value
returns nil
.
Examples
iex> :none |> Result.default_error!("hello")
{:error, "hello"}
iex> :none |> Result.default_error!({})
:error
iex> :none |> Result.default_error!(nil)
** (ArgumentError) Value is nil.
iex> :none |> Result.default_error!(fn -> nil end)
** (ArgumentError) Value is nil.
none_retag(result, new_tag)
Specs
none_retag(result_input(), new_tag) :: new_tag | {new_tag, any()} when new_tag: atom()
If result
is tagged :none
, replaces the tag with new_tag
.
Equivalent to tagged_retag(result, :none, new_tag)
. See tagged_retag/3
.
Examples
iex> :none |> Result.none_retag(:ok)
:ok
iex> :error |> Result.none_retag(:ok)
:error
iex> :ok |> Result.none_retag(:ok)
:ok
iex> :none |> Result.none_retag("string")
** (ArgumentError) Expected atom as new tag, got: "string".
iex> "bare value" |> Result.none_retag(:error)
"bare value"
none_then(result, func_or_value)
Specs
none_then(result_input(), OkThen.Result.Private.func_or_value(out)) :: out when out: any()
If result
is tagged :none
, calls func_or_value
and returns the result. If func_or_value
is not a function, then it is returned as-is.
If result
is not tagged with the specified tag
atom, result
is returned as-is.
Use this function to pipe results into functions that return tagged tuples.
Be aware that no attempt is made to ensure the return value from the function is a tagged tuple.
However, all functions are tolerant of untagged results, and on input will interpret them as an
{:untagged, value}
tuple.
Equivalent to tagged_then(result, :none, func_or_value)
. See tagged_then/3
.
A note about unwrapped nils
If result
is nil
, it is intprereted as :none
. This may be slightly unintuitive, so if
you're curious, this is the reason:
Untagged results are internally wrapped as an {:untagged, any()}
using Result.from_as(value, :untagged)
, and if value
is nil
, the return value of Result.from_as/2
will always be
:none
.
Examples
iex> :none |> Result.none_then(:ok)
:ok
iex> :none |> Result.none_then(fn {} -> {:ok, "hello"} end)
{:ok, "hello"}
iex> :error |> Result.none_then(fn -> {:ok, "hello"} end)
:error
iex> :error |> Result.none_then(fn _ -> {:ok, "hello"} end)
:error
iex> {:error, 1} |> Result.none_then(fn _ -> {:ok, "hello"} end)
{:error, 1}
iex> {:error, 1, 2} |> Result.none_then(fn _ -> {:ok, "hello"} end)
{:error, 1, 2}
iex> :something_else |> Result.none_then(fn _ -> {:ok, "hello"} end)
:something_else
iex> "bare value" |> Result.none_then(:ok)
"bare value"
iex> "bare value" |> Result.none_then(fn _ -> :ok end)
"bare value"
iex> nil |> Result.none_then(:ok)
:ok
Link to this section Functions (any tag)
Link to this section Functions
from(value)
Specs
Converts value
into a maybe(v)
result: {:ok, value} | :none
If value
is nil
, then the result will be :none
. See also from!/1
.
Otherwise, the result will be a two-element tuple, where the first element is :ok
, and the
second element is value
.
Examples
iex> Result.from("hello")
{:ok, "hello"}
iex> Result.from({1, 2})
{:ok, {1, 2}}
iex> Result.from({})
:ok
iex> Result.from(nil)
:none
from!(value)
Specs
Same as from/1
, except raises ArgumentError
if value
is nil
.
Examples
iex> Result.from!("hello")
{:ok, "hello"}
iex> Result.from!({1, 2})
{:ok, {1, 2}}
iex> Result.from!(nil)
** (ArgumentError) Value is nil.
from_as(value, tag)
Specs
Converts value
into a maybe_is(tag)
result: {atom(), any()} | :none
If value
is nil
, then the result will be :none
. See also from_as!/2
.
Otherwise, the result will be a two-element tuple, where the first element is the provided tag,
and the second element is value
.
Examples
iex> "hello" |> Result.from_as(:ok)
{:ok, "hello"}
iex> Result.from_as({1, 2}, :something)
{:something, {1, 2}}
iex> Result.from_as({}, :any_atom)
:any_atom
iex> Result.from_as(nil, :ok)
:none
from_as!(value, tag)
Specs
Same as from_as/2
, except raises ArgumentError
if value
is nil
.
Examples
iex> "hello" |> Result.from_as!(:ok)
{:ok, "hello"}
iex> nil |> Result.from_as!(:ok)
** (ArgumentError) Value is nil.
from_error(value)
Specs
from_error(e) :: maybe_error(e) when e: any()
Converts value
into a maybe_error(e)
result: {:error, value} | :none
If value
is nil
, then the result will be :none
. See also from_error!/1
.
Otherwise, the result will be a two-element tuple, where the first element is :error
, and the
second element is value
.
Examples
iex> Result.from_error("hello")
{:error, "hello"}
iex> Result.from_error({1, 2})
{:error, {1, 2}}
iex> Result.from_error({})
:error
iex> Result.from_error(nil)
:none
from_error!(value)
Specs
Same as from_error/1
, except raises ArgumentError
if value
is nil
.
Examples
iex> Result.from_error!("hello")
{:error, "hello"}
iex> Result.from_error!({1, 2})
{:error, {1, 2}}
iex> Result.from_error!(nil)
** (ArgumentError) Value is nil.
normalize(result, default_tag \\ :untagged)
Specs
normalize(result_input(), atom()) :: tagged()
Converts result
from a variety of accepted result-like terms into an atom or a two-element
tagged tuple.
If result
is not a tagged tuple, it is wrapped as a new result
Examples
iex> Result.normalize(:ok)
:ok
iex> Result.normalize({:ok, "hello"})
{:ok, "hello"}
iex> Result.normalize({:ok, 1, 2})
{:ok, {1, 2}}
iex> Result.normalize(:error)
:error
iex> Result.normalize({:error, "hello"})
{:error, "hello"}
iex> Result.normalize({:error, 1, 2})
{:error, {1, 2}}
iex> Result.normalize(:none)
:none
iex> Result.normalize({:strange, ["hello", 1, 2]})
{:strange, ["hello", 1, 2]}
iex> Result.normalize("hello")
{:untagged, "hello"}
iex> Result.normalize({1, 2})
{:untagged, {1, 2}}
iex> Result.normalize({})
:untagged
iex> Result.normalize({1, 2}, :error)
{:error, {1, 2}}
iex> Result.normalize(nil)
:none
iex> Result.normalize(nil, :error)
:none
normalize!(result)
Specs
normalize!(result_input()) :: tagged()
Same as normalize/1
, except raises ArgumentError
if value
is untagged.
Examples
iex> Result.normalize({:ok, "hello"})
{:ok, "hello"}
iex> Result.normalize!("hello")
** (ArgumentError) Result is untagged: "hello"