Elixir元组 #

一、元组基础 #

1.1 元组定义 #

元组是固定大小的有序集合,使用花括号定义:

elixir
iex(1)> {1, 2, 3}
{1, 2, 3}

iex(2)> {:ok, "Success"}
{:ok, "Success"}

iex(3)> {:error, :not_found}
{:error, :not_found}

iex(4)> {1, "two", :three}
{1, "two", :three}

1.2 元组特性 #

  • 固定大小,创建后不能改变
  • 内存连续存储
  • 随机访问O(1)
  • 适合存储少量固定元素
elixir
iex(1)> tuple = {1, 2, 3}
{1, 2, 3}

iex(2)> tuple_size(tuple)
3

iex(3)> elem(tuple, 0)
1

iex(4)> elem(tuple, 2)
3

1.3 元组与列表的区别 #

特性 元组 列表
大小 固定 可变
内存 连续 链式
随机访问 O(1) O(n)
修改 O(n) 头部O(1)
用途 固定结构 动态集合

二、元组操作 #

2.1 访问元素 #

elixir
iex(1)> tuple = {:ok, 42, "result"}
{:ok, 42, "result"}

iex(2)> elem(tuple, 0)
:ok

iex(3)> elem(tuple, 1)
42

iex(4)> elem(tuple, 2)
"result"

iex(5)> tuple_size(tuple)
3

2.2 修改元素 #

elixir
iex(1)> tuple = {1, 2, 3}
{1, 2, 3}

iex(2)> put_elem(tuple, 1, :two)
{1, :two, 3}

iex(3)> tuple
{1, 2, 3}

注意:元组是不可变的,put_elem 返回新元组。

2.3 追加元素 #

elixir
iex(1)> tuple = {1, 2, 3}
{1, 2, 3}

iex(2)> Tuple.append(tuple, 4)
{1, 2, 3, 4}

iex(3)> Tuple.insert_at(tuple, 1, :inserted)
{1, :inserted, 2, 3}

2.4 删除元素 #

elixir
iex(1)> tuple = {1, 2, 3}
{1, 2, 3}

iex(2)> Tuple.delete_at(tuple, 1)
{1, 3}

2.5 转换 #

elixir
iex(1)> Tuple.to_list({1, 2, 3})
[1, 2, 3]

iex(2)> List.to_tuple([1, 2, 3])
{1, 2, 3}

三、模式匹配 #

3.1 基本匹配 #

elixir
iex(1)> {a, b, c} = {1, 2, 3}
{1, 2, 3}

iex(2)> a
1

iex(3)> b
2

iex(4)> c
3

3.2 大小匹配 #

元组大小必须匹配:

elixir
iex(1)> {a, b} = {1, 2, 3}
** (MatchError) no match of right hand side value: {1, 2, 3}

iex(1)> {a, b, c} = {1, 2}
** (MatchError) no match of right hand side value: {1, 2}

3.3 忽略元素 #

elixir
iex(1)> {a, _, c} = {1, 2, 3}
{1, 2, 3}

iex(2)> a
1

iex(3)> c
3

3.4 嵌套匹配 #

elixir
iex(1)> {a, {b, c}} = {1, {2, 3}}
{1, {2, 3}}

iex(2)> a
1

iex(3)> b
2

iex(4)> c
3

3.5 值匹配 #

elixir
iex(1)> {:ok, result} = {:ok, "Success"}
{:ok, "Success"}

iex(2)> result
"Success"

iex(3)> {:ok, result} = {:error, "Failed"}
** (MatchError) no match of right hand side value: {:error, "Failed"}

四、常见使用模式 #

4.1 函数返回值 #

元组常用于函数返回值,表示成功或失败:

elixir
defmodule FileProcessor do
  def read_file(path) do
    case File.read(path) do
      {:ok, content} -> {:ok, process(content)}
      {:error, reason} -> {:error, reason}
    end
  end

  defp process(content) do
    content
    |> String.split("\n")
    |> Enum.map(&String.trim/1)
  end
end

4.2 处理结果 #

elixir
def handle_result(result) do
  case result do
    {:ok, data} ->
      IO.puts("Success: #{data}")

    {:error, :not_found} ->
      IO.puts("Not found")

    {:error, reason} ->
      IO.puts("Error: #{reason}")
  end
end

4.3 多返回值 #

elixir
defmodule Math do
  def divmod(a, b) do
    {div(a, b), rem(a, b)}
  end
end

{quotient, remainder} = Math.divmod(10, 3)

4.4 配置选项 #

elixir
defmodule Config do
  def parse({:database, host, port}) do
    %{host: host, port: port}
  end

  def parse({:cache, ttl}) do
    %{ttl: ttl}
  end
end

4.5 坐标表示 #

elixir
defmodule Point do
  def distance({x1, y1}, {x2, y2}) do
    :math.sqrt(:math.pow(x2 - x1, 2) + :math.pow(y2 - y1, 2))
  end

  def move({x, y}, {dx, dy}) do
    {x + dx, y + dy}
  end
end

五、两元素元组 #

5.1 键值对 #

两元素元组常用于表示键值对:

elixir
iex(1)> {:name, "Alice"}
{:name, "Alice"}

iex(2)> [{:a, 1}, {:b, 2}, {:c, 3}]
[a: 1, b: 2, c: 3]

5.2 构建映射 #

elixir
iex(1)> Enum.into([{:a, 1}, {:b, 2}], %{})
%{a: 1, b: 2}

5.3 关键字列表 #

关键字列表是两元素元组的列表:

elixir
iex(1)> [a: 1, b: 2]
[a: 1, b: 2]

iex(2)> [{:a, 1}, {:b, 2}]
[a: 1, b: 2]

六、元组标签 #

6.1 标签元组 #

第一个元素作为标签:

elixir
defmodule Shape do
  def area({:rectangle, width, height}) do
    width * height
  end

  def area({:circle, radius}) do
    :math.pi() * radius * radius
  end

  def area({:triangle, base, height}) do
    0.5 * base * height
  end
end

6.2 使用示例 #

elixir
iex(1)> Shape.area({:rectangle, 5, 3})
15

iex(2)> Shape.area({:circle, 2})
12.566370614359172

iex(3)> Shape.area({:triangle, 4, 3})
6.0

七、记录 #

7.1 定义记录 #

记录是带命名元素的元组:

elixir
defmodule User do
  require Record
  Record.defrecord(:user, name: nil, age: 0, email: nil)
end

7.2 使用记录 #

elixir
iex(1)> require User
User

iex(2)> u = User.user(name: "Alice", age: 30)
{:user, "Alice", 30, nil}

iex(3)> User.user(u, :name)
"Alice"

iex(4)> User.user(u, :age)
30

八、性能考虑 #

8.1 元组优势 #

elixir
tuple = {1, 2, 3, 4, 5}
elem(tuple, 4)

8.2 元组劣势 #

elixir
tuple = {1, 2, 3, 4, 5}
put_elem(tuple, 2, :new)

8.3 选择建议 #

场景 推荐
固定大小数据 元组
动态大小数据 列表
命名字段 映射或结构体
函数返回值 标签元组

九、与Erlang互操作 #

9.1 Erlang记录 #

Erlang记录在Elixir中是元组:

elixir
iex(1)> :erlang.time()
{22, 15, 30}

iex(2)> :erlang.date()
{2024, 1, 15}

9.2 处理Erlang返回值 #

elixir
case :file.read_file("test.txt") do
  {:ok, binary} -> process_binary(binary)
  {:error, :enoent} -> {:error, "File not found"}
  {:error, reason} -> {:error, reason}
end

十、总结 #

本章学习了:

操作 示例
创建 {1, 2, 3}
访问 elem(tuple, 0)
修改 put_elem(tuple, 0, :new)
大小 tuple_size(tuple)
转换 Tuple.to_list/1
模式匹配 {a, b, c} = tuple

准备好学习映射了吗?让我们进入下一章。

最后更新:2026-03-27