ELIXIR / CHAPTER 05
Composing tagged results with with
IntermediateKeep 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.
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){: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