My Favorite Functions and Patterns: With Statement

This is just one segment in a compilation of my favorite functions and patterns in functional programming. This bit focuses on the with statement. For more, visit the Index where I share the rest.

The with statement may be my favorite feature of Elixir since the pipe operator. It enables the chaining of uncertainty. It affords elegance to the otherwise unsavory business of nested control structures.

There are few things in code more corrupting of beauty than:


case fetch_token() do
  {:ok, token} ->
    case call_outside_server(token) do
      {:ok, resp} ->
        case write_to_db(resp) do
          {:ok, db_entry} -> db_entry
          error -> error
        end

      error ->
        error
    end

  error ->
    error
end

I encounter this pattern all the time, and I never fail to shudder. Let’s try again:


with {:ok, token} <- fetch_token(),
     {:ok, resp} <- call_outside_server(token),
     {:ok, db_entry} <- write_to_db(resp) do
  db_entry
else
  error -> error
end

What’s happening? with evaluates each expression to the right of <-. Provided the result matches, it continues down the chain; if the entire chain is successful, code following do is executed. Provided any result in the chain doesn’t match, its value is passed to the else statement. Hence, we can flatten our nested control structures to resemble something more like a pipeline, as well as consolidate redundant error handling in one place.

with also permits evaluation of bare expressions. Let’s say we need to perform a calculation on the response of call_outside_server/1 before passing it to write_to_db. Turns out that’s easy:


with {:ok, token} <- fetch_token(),
     {:ok, resp} <- call_outside_server(token),
     resp = groom_response(resp),
     {:ok, db_entry} <- write_to_db(resp) do
  db_entry
else
  error -> error
end

Further reading

The Revelry Blog is where we learn in public.

Read more from our engineering, design, product, sales, and growth teams.

Check out our Open Source repositories here.

More Posts by Jonathan Walters:

Kubernetes, Delivered

Deploy your first app within 24 hours. Book a demo to get started.