Thank you very much @Eiji, I took you example sample
and I created a functional example / comparison of my old cold and your recommended new code with recursion.
Just one small correction - second sample
has do: default
and I didn’t use default value for default
argument.
defmodule DoSomething do
def function_that_shoud_not_fail(value) do
# dummy code
# {:error, :this_is_not_expected_terminate_me_now}
{:ok, value <> "-abc"}
end
def another_function(value) do
# dummy code
# {:error, :this_is_normal}
{:ok, value <> "-xyz"}
end
#####################################################
# old way
def test_this_using_reduce_while(enumerable) do
Enum.reduce_while(enumerable, {:error, :enumerable_is_empty}, fn single_element, _ ->
with {:ok, value} <- function_that_shoud_not_fail(single_element),
{:ok, _} = result <- another_function(value) do
# sucess -> finish (halt)
{:halt, result}
else
# continue processing other elements / finish with this error
{:error, :this_is_normal} = result -> {:cont, result}
# unknown exception -> halt immediately
{:error, _} = result -> {:halt, result}
end
end)
end
#####################################################
# new way
defp sample([], default, _func),
do: default
defp sample([head | tail], _default, func) do
case func.(head) do
# sucess -> finish (halt)
{:ok, _} = result -> result
# continue processing other elements / finish with this error
{:error, :this_is_normal} = error -> sample(tail, error, func)
# unknown error -> finish (halt)
{:error, _} = error -> error
end
end
def test_this_using_recursion(enumerable) do
sample(enumerable, {:error, :enumerable_is_empty}, fn single_element ->
with {:ok, value} <- function_that_shoud_not_fail(single_element),
{:ok, _} = result <- another_function(value) do
result
else
{:error, _} = error -> error
end
end)
end
#####################################################
end
result = DoSomething.test_this_using_reduce_while(["aaa", "bbb", "ccc", "ddd", "eee", "fff"])
IO.puts("result: #{inspect(result)}")
result = DoSomething.test_this_using_recursion(["aaa", "bbb", "ccc", "ddd", "eee", "fff"])
IO.puts("result: #{inspect(result)}")
That would basically create Enum.reduce_while
that doesn’t have acc
. Very cool
.