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. 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