ELIXIR / CHAPTER 05

Composing tagged results with with

Intermediate

Keep dependent success paths readable without hiding failures.

By the end of this chapter

  • Match success tuples in a with chain
  • Distinguish <- from raising assignment
  • Handle actual nonmatching values in else

The idea

A with expression sequences operations whose results must match expected patterns. A clause using <- continues when its pattern matches and exits with the unmatched value otherwise. This is useful for tagged results such as {:ok, value} and {:error, reason}, where each later operation depends on a successful earlier value.

An else block handles the values that failed to match; it does not receive an automatic exception or a universal error type. Match the actual shapes each step can return. Variables introduced inside with are local to that expression and should be returned explicitly when needed outside. Avoid collapsing distinct errors into one vague result when callers need to choose different recovery actions.

Elixir example
result = with {:ok, n} <- {:ok, 4},
              true <- n > 0 do
  {:ok, n * 2}
else
  false -> {:error, :nonpositive}
  {:error, reason} -> {:error, reason}
end
IO.inspect(result)
Result
{:ok, 8}

Both patterns match, so the success block doubles the value. A false guard result would take its explicit else branch.

Try it yourself

Chain decoding and domain validation while preserving their distinct failure reasons.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

What does a failed <- pattern do inside with?