I tried to find a solution for early return online, however, the results did not satisfy me. The multiple pattern matching functions, or the try/catch/rescue don't make the code easier to read (IMO).
I have a problem looking like this: get from 1, if not has, get from 2, if still not has, get from 3.
If I use the with/else, the code would look like this:
with {:get_1, {:ok, res_1}} <- {:get_1, get_1()} do
{:ok, res_1}
else
{:error, :not_found} ->
with {:get_2, {:ok, res_2}} <- {:get_2, get_2()} do
{:ok, res_2}
else
{:get_2, {:error, :not_found}} ->
get_3()
{:get_2, any} -> any
end
{:get_1, any} ->
any
end
This is just a simple one since I just care about one type of error (:not_found). It would look uglier if we had to care for more error handlings.
Then, I came up with a solution: next_then()
def next_then(:next, next), do: next.(:none)
def next_then({:next, prev_result}, next), do: next.(prev_result)
def next_then(prev_result, next), do: prev_result
The re-written code would look like this:
case get_1() do
{:error, :not_found} -> :next
any -> any
end
|> next_then(fn _ ->
case get_2() do
{:error, :not_found} -> :next
any -> any
end
end)
|> next_then(fn _ ->
get_3()
end)
Note: related design pattern: Chain of Responsibility.
Top comments (0)