# Copyright(c) 2015-2023 ACCESS CO., LTD. All rights reserved.
use Croma
defmodule Antikythera.EnumUtil do
@moduledoc """
Utility functions to work with enumerables.
"""
@type context :: any
@type element :: Enum.element()
@not_found_error_msg "no matching element found"
@doc """
Updates items of an enumerable with the given function, depending on context.
Context can be `any`.
The function `fun` takes item and context as arguments, and must achieve 2 purposes:
1. Update an item according to current context
2. Produces new context for next item
then, return both as tuple `{new_item, new_context}`.
"""
defun map_with_context(
e :: Enum.t(),
c :: context,
fun :: (element, context -> {element, context})
) :: [element] do
Enum.map_reduce(e, c, fun) |> elem(0)
end
@doc """
A variant of `Enum.find/2` that raises an exception when no matching element is found.
"""
defun find!(e :: Enum.t(), fun :: (element -> any)) :: element do
Enum.find(e, fun) || raise @not_found_error_msg
end
@doc """
A variant of `Enum.find_value/2` that raises an exception when no matching element is found.
"""
defun find_value!(e :: Enum.t(), fun :: (element -> any)) :: any do
Enum.find_value(e, fun) || raise @not_found_error_msg
end
end