DEV Community

Percy Pham
Percy Pham

Posted on • Edited on

Early Return in Elixir

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Note: related design pattern: Chain of Responsibility.

Top comments (0)