Control Flow
if is a macro; it returns nil when the condition is falsy and there is no else.
9.1 case
case File.read("config.txt") do
{:ok, contents} -> String.length(contents)
{:error, :enoent} -> IO.puts("not found"); 0
{:error, reason} -> raise "failed: #{inspect(reason)}"
end
case x do
n when n > 10 -> :big
_ -> :small
end9.2 cond — first truthy condition
cond do
temp < 0 -> "freezing"
temp < 20 -> "cold"
temp < 30 -> "warm"
true -> "hot" # default branch
end9.3 if / unless
if is a macro; it returns nil when the condition is falsy and there is no else.
if age >= 18, do: "adult", else: "minor"
if logged_in? do
show_dashboard()
else
redirect()
end
unless valid?, do: raise("invalid")9.4 with — chaining matches
If any clause fails to match, with returns that value (or goes to else). Guards allowed: {:ok, n} when n > 0 <- get(). Bare expressions: x = compute().
with {:ok, user} <- fetch_user(id),
{:ok, account} <- fetch_account(user),
:ok <- check_balance(account, amount) do
transfer(account, amount)
else
{:error, :not_found} -> {:error, "user not found"}
{:error, reason} -> {:error, reason}
end9.5 Everything is an expression
Variables bound inside if/case don't leak out — return values instead:
result = if x > 0, do: :pos, else: :neg# Wrong (doesn't work):
if cond, do: x = 1
# Right:
x = if cond, do: 1, else: 0