OptionEx v0.2.0 OptionEx View Source

OptionEx is a module for handling functions returning a OptionEx.t/0. This module is inspired by the f# Option module, and Railway Oriented Programming as explained by Scott Wlaschin. This module is intended to make working with nil values more safe and convenient. For splitting tracks based on ok or error return values see ResultEx.

The Option type consists of either a {:some, term} where the term represents a value, or the :none atom representing the lack of a value.

By replacing optional nil values with an OptionEx.t/0, it is no longer needed to match nil value cases. By using OptionEx.map/2 or OptionEx.bind/2 the function passed as second argument will only be executed when a value is present. By using OptionEx.or_else/2 or OptionEx.or_else_with/2 it is possible to add a default value, or behaviour to be executed only in case there is no value.

Examples

iex> find_by_id = fn
...>   1 -> nil
...>   x -> %{id: x}
...> end
...>
...> find_by_id.(2)
...> |> OptionEx.return()
{:some, %{id: 2}}
...>
...> find_by_id.(1)
...> |> OptionEx.return()
:none
...>
...> find_by_id.(2)
...> |> OptionEx.return()
...> |> OptionEx.map(fn record -> record.id end)
...> |> OptionEx.map(&(&1 + 1))
...> |> OptionEx.bind(find_by_id)
{:some, %{id: 3}}
...>
...> find_by_id.(1)
...> |> OptionEx.return()
...> |> OptionEx.map(fn record -> record.id end)
...> |> OptionEx.map(&(&1 + 1))
...> |> OptionEx.bind(find_by_id)
:none
...>
...> find_by_id.(2)
...> |> OptionEx.return()
...> |> OptionEx.or_else_with(fn -> find_by_id.(0) end)
%{id: 2}
...>
...> find_by_id.(1)
...> |> OptionEx.return()
...> |> OptionEx.or_else_with(fn -> find_by_id.(0) end)
%{id: 0}

Link to this section Summary

Types

t()

Data structure representing an Option. When the Option is containing a value, the value is wrapped in a tuple with the atom :some as its first element. When the Option is empty, it is represented as the single atom :none

Functions

Executes or partially executes the function given as value of the first OptionEx.t/0, and applies it with the value of the second OptionEx.t/0. If the function has an arity greater than 1, the returned OptionEx.t/0 value will be the function partially applied. (The function name is ‘appl’ rather than ‘apply’ to prevent import conflicts with ‘Kernel.apply’)

Partially applies OptionEx.bind/2 with the passed function

Applies a function with the value of the OptionEx.t/0. The passed function is expected to return an OptionEx.t/0. This can be useful for chaining functions that elevate values into options together

Unwraps the OptionEx.t/0 to return its value. The second argument will be a specific error message to throw when the OptionEx.t/0 is empty

Filters an Enum.t/0 from all :none values

Flatten nested OptionEx.t/0s into one OptionEx.t/0

Flattens an Enum.t/0 of OptionEx.t/0s into an OptionEx.t/0 of enumerables

Creates an OptionEx.t/0 from a boolean, and the specified value. If the boolean is true, an option with the value is returned. If the boolean is false, :none is returned

Partially applies OptionEx.map/2 with the passed function

Runs a function against the OptionEx.t/0 value

Unwraps the OptionEx.t/0 to return its value. If the OptionEx.t/0 is empty, it will return the default value passed as second argument instead

Unwraps the OptionEx.t/0 to return its value. If the OptionEx.t/0 is empty, the given function will be applied instead

Attempts to generate a different option wrapped value by executing the function passed, if the OptionEx.t/0 is empty. If the original OptionEx.t/0 contains a value, the OptionEx.t/0 is returned without unwrapping the value

Elevates a value to an OptionEx.t/0 type. If nil is passed, an empty OptionEx.t/0 will be returned

Converts an OptionEx.t/0 to a bool, ignoring the inner value

Converts an OptionEx.t/0 to a result type

Converts an OptionEx.t/0 to a Result type, specifying the error reason in case the OptionEx.t/0 is empty. The Result type consists of an {:ok, term} tuple, or an {:error, term} tuple

Unwraps the OptionEx.t/0 to return its value. Throws an error if the OptionEx.t/0 is :none

Link to this section Types

Link to this type t() View Source
t() :: {:some, term()} | :none

Data structure representing an Option. When the Option is containing a value, the value is wrapped in a tuple with the atom :some as its first element. When the Option is empty, it is represented as the single atom :none.

Link to this section Functions

Link to this function appl(arg1, arg2) View Source
appl(t(), t()) :: t()

Executes or partially executes the function given as value of the first OptionEx.t/0, and applies it with the value of the second OptionEx.t/0. If the function has an arity greater than 1, the returned OptionEx.t/0 value will be the function partially applied. (The function name is ‘appl’ rather than ‘apply’ to prevent import conflicts with ‘Kernel.apply’)

Examples

iex> value_option = {:some, 1}
...> function_option = {:some, fn value -> value + 1 end}
...> OptionEx.appl(function_option, value_option)
{:some, 2}

iex> {:some, fn value1, value2, value3 -> value1 + value2 + value3 end}
...> |> OptionEx.appl({:some, 1})
...> |> OptionEx.appl({:some, 2})
...> |> OptionEx.appl({:some, 3})
{:some, 6}

iex> :none
...> |> OptionEx.appl({:some, 1})
...> |> OptionEx.appl({:some, 1})
...> |> OptionEx.appl({:some, 1})
:none

iex> {:some, fn value1, value2, value3 -> value1 + value2 + value3 end}
...> |> OptionEx.appl({:some, 1})
...> |> OptionEx.appl({:some, 1})
...> |> OptionEx.appl(:none)
:none
Link to this function bind(fun) View Source
bind((term() -> t())) :: (t() -> t())

Partially applies OptionEx.bind/2 with the passed function.

Link to this function bind(arg1, fun) View Source
bind(t(), (term() -> t())) :: t()

Applies a function with the value of the OptionEx.t/0. The passed function is expected to return an OptionEx.t/0. This can be useful for chaining functions that elevate values into options together.

Examples

iex> head = fn
...>   [] -> :none
...>   list -> {:some, hd(list)}
...> end
...> head.([[4]])
...> |> OptionEx.bind(head)
{:some, 4}

iex> head = fn
...>   [] -> :none
...>   list -> {:some, hd(list)}
...> end
...> head.([[]])
...> |> OptionEx.bind(head)
:none
Link to this function expect!(arg1, message) View Source
expect!(t(), String.t()) :: term()

Unwraps the OptionEx.t/0 to return its value. The second argument will be a specific error message to throw when the OptionEx.t/0 is empty.

Examples

iex> OptionEx.return(5)
...> |> OptionEx.expect!("The value was not what was expected")
5
Link to this function filter_enum(enum) View Source
filter_enum(Enum.t()) :: Enum.t()

Filters an Enum.t/0 from all :none values.

Examples

iex> [{:some, 1}, :none, {:some, 3}]
...> |> OptionEx.filter_enum()
[{:some, 1}, {:some, 3}]

iex> %{a: {:some, 1}, b: :none, c: {:some, 3}}
...> |> OptionEx.filter_enum()
%{a: {:some, 1}, c: {:some, 3}}
Link to this function flatten(result) View Source
flatten(t()) :: t()

Flatten nested OptionEx.t/0s into one OptionEx.t/0.

Examples

iex> OptionEx.return(5)
...> |> OptionEx.return()
...> |> OptionEx.return()
...> |> OptionEx.flatten()
{:some, 5}

iex> {:some, {:some, :none}}
...> |> OptionEx.flatten()
:none
Link to this function flatten_enum(enum) View Source
flatten_enum(Enum.t()) :: t()

Flattens an Enum.t/0 of OptionEx.t/0s into an OptionEx.t/0 of enumerables.

Examples

iex> [{:some, 1}, {:some, 2}, {:some, 3}]
...> |> OptionEx.flatten_enum()
{:some, [1, 2, 3]}

iex> [{:some, 1}, :none, {:some, 3}]
...> |> OptionEx.flatten_enum()
:none

iex> %{a: {:some, 1}, b: {:some, 2}, c: {:some, 3}}
...> |> OptionEx.flatten_enum()
{:some, %{a: 1, b: 2, c: 3}}

iex> %{a: {:some, 1}, b: :none, c: {:some, 3}}
...> |> OptionEx.flatten_enum()
:none
Link to this function from_bool(bool, value) View Source
from_bool(boolean(), term()) :: t()

Creates an OptionEx.t/0 from a boolean, and the specified value. If the boolean is true, an option with the value is returned. If the boolean is false, :none is returned.

Examples

iex> OptionEx.from_bool(true, :unit)
{:some, :unit}

iex> OptionEx.from_bool(false, :unit)
:none
Link to this function map(fun) View Source
map((term() -> term())) :: (t() -> t())

Partially applies OptionEx.map/2 with the passed function.

Link to this function map(arg1, fun) View Source
map(t(), (term() -> term())) :: t()

Runs a function against the OptionEx.t/0 value.

Examples

iex> option = {:some, 1}
...> OptionEx.map(option, &(&1 + 1))
{:some, 2}

iex> option = :none
...> OptionEx.map(option, &(&1 + 1))
:none 
Link to this function or_else(arg1, default) View Source
or_else(t(), term()) :: term()

Unwraps the OptionEx.t/0 to return its value. If the OptionEx.t/0 is empty, it will return the default value passed as second argument instead.

Examples

iex> OptionEx.return(5)
...> |> OptionEx.or_else(4)
5

iex> :none
...> |> OptionEx.or_else(4)
4
Link to this function or_else_with(arg1, fun) View Source
or_else_with(t(), (() -> term())) :: term()

Unwraps the OptionEx.t/0 to return its value. If the OptionEx.t/0 is empty, the given function will be applied instead.

Examples

iex> OptionEx.return(5)
...> |> OptionEx.or_else_with(fn -> 4 end)
5

iex> :none
...> |> OptionEx.or_else_with(fn -> 4 end)
4
Link to this function or_try(arg1, fun) View Source
or_try(t(), (() -> t())) :: t()

Attempts to generate a different option wrapped value by executing the function passed, if the OptionEx.t/0 is empty. If the original OptionEx.t/0 contains a value, the OptionEx.t/0 is returned without unwrapping the value.

The passed function is expected to return a OptionEx.t/0.

Examples

iex> attempt_to_get_data = fn -> :none end
...> successfully_get_data = fn -> {:some, :data} end
...>
...> attempt_to_get_data.()
...> |> OptionEx.or_try(attempt_to_get_data)
...> |> OptionEx.or_try(successfully_get_data)
...> |> OptionEx.or_try(attempt_to_get_data)
{:some, :data}
Link to this function return(value) View Source
return(term()) :: t()

Elevates a value to an OptionEx.t/0 type. If nil is passed, an empty OptionEx.t/0 will be returned.

Examples

iex> OptionEx.return(1)
{:some, 1}

iex> OptionEx.return(nil)
:none
Link to this function to_bool(arg1) View Source
to_bool(t()) :: boolean()

Converts an OptionEx.t/0 to a bool, ignoring the inner value.

Examples

iex> OptionEx.to_bool({:some, 5})
true
...> OptionEx.to_bool(:none)
false
Link to this function to_result(arg1) View Source
to_result(t()) :: {:ok, term()} | {:error, String.t()}

Converts an OptionEx.t/0 to a result type.

Examples

iex> OptionEx.to_result({:some, 5})
{:ok, 5}
...> OptionEx.to_result(:none)
{:error, "OptionEx.to_result: The option was empty"}
Link to this function to_result(arg1, reason) View Source
to_result(t(), term()) :: {:ok, term()} | {:error, term()}

Converts an OptionEx.t/0 to a Result type, specifying the error reason in case the OptionEx.t/0 is empty. The Result type consists of an {:ok, term} tuple, or an {:error, term} tuple.

Examples

iex> OptionEx.to_result({:some, 5}, :unexpected_empty_value)
{:ok, 5}
...> OptionEx.to_result(:none, :unexpected_empty_value)
{:error, :unexpected_empty_value}
Link to this function unwrap!(arg1) View Source
unwrap!(t()) :: term()

Unwraps the OptionEx.t/0 to return its value. Throws an error if the OptionEx.t/0 is :none.

Examples

iex> OptionEx.return(5)
...> |> OptionEx.unwrap!()
5