Current section
Files
Jump to
Current section
Files
lib/enum.ex
defmodule Rivet.Utils.Enum do
@moduledoc """
Contributor: Brandon Gillespie
"""
@doc """
like Enum.find_value() on a list of [{rx, fn}, ..], calling fn on the matched
rx and returning the result. Almost like a case statement (see to_minutes below)
iex> opts = [
...> {~r/^(\\d+)\\s*(m|min(s)?|minute(s)?)$/, fn match, _ -> {:min, match} end},
...> {~r/^(\\d+)\\s*(h|hour(s)?|hr(s)?)$/, fn match, _ -> {:hr, match} end},
...> ]
...> enum_rx(opts, "30 m")
{:min, ["30 m", "30", "m"]}
iex> enum_rx(opts, "1.5 hr") # doesn't match because of the period
nil
"""
def enum_rx([], _str), do: nil
def enum_rx(elems, str) do
[elem | elems] = elems
{rx, func} = elem
case Regex.run(rx, str) do
nil ->
enum_rx(elems, str)
match ->
func.(match, str)
end
end
@doc """
sequence helps you know if any item in a list of tuples failed
iex> vals = [ok: 1, ok: 2, ok: 3]
...> sequence(vals)
{:ok, [1,2,3]}
iex> vals = [ok: 1, error: "nan", ok: 3]
...> sequence(vals)
{:error, "nan"}
"""
@spec sequence(list(keyword())) :: {:error, any()} | {:ok, list(any())}
def sequence(keywords) do
keywords
|> Enum.reverse()
|> Enum.reduce({:ok, []}, fn
_, {:error, err} -> {:error, err}
{:error, err}, _ -> {:error, err}
{:ok, val}, {:ok, vals} -> {:ok, [val | vals]}
end)
end
end