Elixir条件语句 #

一、if与unless #

1.1 if基本语法 #

elixir
iex(1)> if true do
...>   "True branch"
...> end
"True branch"

iex(2)> if false do
...>   "True branch"
...> end
nil

1.2 if-else #

elixir
iex(1)> if false do
...>   "True branch"
...> else
...>   "False branch"
...> end
"False branch"

1.3 单行语法 #

elixir
iex(1)> if true, do: "True", else: "False"
"True"

iex(2)> if true, do: "True"
"True"

1.4 unless #

unlessif 的反向:

elixir
iex(1)> unless false do
...>   "Not false"
...> end
"Not false"

iex(2)> unless true do
...>   "Not true"
...> else
...>   "Is true"
...> end
"Is true"

1.5 真值与假值 #

只有 falsenil 被视为假值:

elixir
iex(1)> if 0, do: "0 is truthy"
"0 is truthy"

iex(2)> if "", do: "empty string is truthy"
"empty string is truthy"

iex(3)> if [], do: "empty list is truthy"
"empty list is truthy"

iex(4)> if nil, do: "nil is truthy"
nil

二、case表达式 #

2.1 基本语法 #

elixir
iex(1)> case {:ok, "Hello"} do
...>   {:ok, result} -> result
...>   {:error, reason} -> "Error: #{reason}"
...> end
"Hello"

2.2 模式匹配 #

elixir
iex(1)> case {1, 2, 3} do
...>   {1, x, 3} -> "Matched with x = #{x}"
...>   {4, 5, 6} -> "Won't match"
...>   _ -> "Match anything"
...> end
"Matched with x = 2"

2.3 守卫子句 #

elixir
iex(1)> case {1, 2, 3} do
...>   {1, x, 3} when x > 0 -> "x is positive: #{x}"
...>   {1, x, 3} when x < 0 -> "x is negative: #{x}"
...>   _ -> "No match"
...> end
"x is positive: 2"

2.4 多个守卫条件 #

elixir
iex(1)> case 5 do
...>   x when x < 0 or x > 10 -> "Out of range"
...>   x when x >= 0 and x <= 10 -> "In range"
...> end
"In range"

2.5 匹配错误 #

如果没有匹配项,会抛出错误:

elixir
iex(1)> case :unknown do
...>   :ok -> "OK"
...> end
** (CaseClauseError) no case clause matching: :unknown

2.6 使用场景 #

处理函数返回值 #

elixir
def process_file(path) do
  case File.read(path) do
    {:ok, content} ->
      process_content(content)

    {:error, :enoent} ->
      {:error, "File not found"}

    {:error, reason} ->
      {:error, "Read error: #{reason}"}
  end
end

处理HTTP响应 #

elixir
def handle_response(response) do
  case response do
    %{status: 200, body: body} ->
      {:ok, parse_body(body)}

    %{status: 404} ->
      {:error, :not_found}

    %{status: status} when status >= 500 ->
      {:error, :server_error}

    %{status: status} when status >= 400 ->
      {:error, :client_error}
  end
end

三、cond表达式 #

3.1 基本语法 #

cond 用于检查多个条件,类似于其他语言的 else if

elixir
iex(1)> cond do
...>   1 + 1 == 3 -> "Wrong"
...>   2 * 2 == 4 -> "Correct"
...>   true -> "Fallback"
...> end
"Correct"

3.2 使用场景 #

分数等级 #

elixir
def grade(score) do
  cond do
    score >= 90 -> "A"
    score >= 80 -> "B"
    score >= 70 -> "C"
    score >= 60 -> "D"
    true -> "F"
  end
end

用户权限 #

elixir
def check_permission(user) do
  cond do
    user.role == :admin -> :full_access
    user.role == :moderator -> :moderate_access
    user.active == false -> :no_access
    user.subscription == :premium -> :premium_access
    true -> :basic_access
  end
end

3.3 注意事项 #

如果没有条件为真,会抛出错误:

elixir
iex(1)> cond do
...>   1 + 1 == 3 -> "Wrong"
...> end
** (CondClauseError) no cond clause evaluated to a true value

四、守卫表达式 #

4.1 允许的表达式 #

守卫中只能使用有限的函数和操作符:

允许的操作符:

  • 比较操作符:==, !=, ===, !==, <, >, <=, >=
  • 布尔操作符:and, or, not, &&, ||, !
  • 算术操作符:+, -, *, /
  • 连接操作符:++, --, <>
  • in 操作符

允许的函数:

  • 类型检查:is_atom/1, is_binary/1, is_bitstring/1, is_boolean/1, is_float/1, is_function/1, is_integer/1, is_list/1, is_map/1, is_number/1, is_pid/1, is_port/1, is_reference/1, is_tuple/1
  • 其他:abs/1, binary_part/3, bit_size/1, byte_size/1, div/2, elem/2, hd/1, length/1, map_size/1, node/0, node/1, rem/2, round/1, self/0, tl/1, trunc/1, tuple_size/1

4.2 示例 #

elixir
defmodule Guard do
  def type_check(x) when is_integer(x), do: "Integer"
  def type_check(x) when is_float(x), do: "Float"
  def type_check(x) when is_binary(x), do: "String"
  def type_check(x) when is_list(x), do: "List"
  def type_check(x) when is_map(x), do: "Map"
  def type_check(x) when is_atom(x), do: "Atom"
  def type_check(_), do: "Unknown"
end

defmodule Math do
  def abs(x) when x < 0, do: -x
  def abs(x), do: x

  def divide(_, 0), do: {:error, :division_by_zero}
  def divide(a, b) when is_number(a) and is_number(b), do: {:ok, a / b}
end

五、条件表达式最佳实践 #

5.1 使用case处理结构化数据 #

elixir
def handle_event(event) do
  case event do
    %{type: :click, target: target} ->
      handle_click(target)

    %{type: :keypress, key: key} when key in ["Enter", "Space"] ->
      handle_action_key(key)

    %{type: :keypress, key: key} ->
      handle_key(key)

    %{type: :scroll, direction: direction} ->
      handle_scroll(direction)
  end
end

5.2 使用cond处理条件逻辑 #

elixir
def calculate_discount(user, order) do
  cond do
    user.membership == :platinum -> 0.20
    user.membership == :gold -> 0.15
    user.membership == :silver -> 0.10
    order.total > 1000 -> 0.05
    true -> 0
  end
end

5.3 使用if处理简单条件 #

elixir
def format_name(name) do
  if name do
    String.trim(name)
  else
    "Anonymous"
  end
end

5.4 避免嵌套 #

elixir
def bad_example(user) do
  if user do
    if user.active do
      if user.admin do
        "Admin access"
      else
        "User access"
      end
    else
      "Inactive"
    end
  else
    "Guest"
  end
end

def good_example(user) do
  case user do
    nil -> "Guest"
    %{active: false} -> "Inactive"
    %{admin: true} -> "Admin access"
    _ -> "User access"
  end
end

六、do块语法 #

6.1 多行语法 #

elixir
if condition do
  statement1
  statement2
end

6.2 关键字语法 #

elixir
if condition, do: statement

if condition do
  statement1
else
  statement2
end

6.3 混合语法 #

elixir
if condition,
  do: statement1,
  else: statement2

七、总结 #

本章学习了:

表达式 用途
if 简单条件判断
unless 反向条件判断
case 模式匹配多分支
cond 条件表达式多分支
守卫子句 模式匹配中的条件约束

准备好学习模式匹配进阶了吗?让我们进入下一章。

最后更新:2026-03-27