Erlang元组 #

一、元组概述 #

元组是Erlang中用于存储固定数量元素的复合数据类型,元素可以是不同类型。

1.1 元组的特点 #

  • 固定大小
  • 元素可以是任意类型
  • 访问元素通过位置索引
  • 常用于表示结构化数据

二、元组定义 #

2.1 基本定义 #

erlang
-module(tuple_def).
-export([demo/0]).

demo() ->
    Empty = {},
    Pair = {1, 2},
    Triple = {a, b, c},
    Mixed = {1, "hello", atom, [1, 2, 3]},
    Nested = {1, {2, 3}, {4, {5, 6}}},
    
    io:format("Empty: ~p~n", [Empty]),
    io:format("Pair: ~p~n", [Pair]),
    io:format("Triple: ~p~n", [Triple]),
    io:format("Mixed: ~p~n", [Mixed]),
    io:format("Nested: ~p~n", [Nested]),
    ok.

2.2 标签元组 #

元组的第一个元素通常是原子,作为标签:

erlang
-module(tagged_tuple).
-export([demo/0]).

demo() ->
    Point = {point, 10, 20},
    Person = {person, "Alice", 30},
    Result = {ok, "Success"},
    Error = {error, "Something went wrong"},
    
    io:format("Point: ~p~n", [Point]),
    io:format("Person: ~p~n", [Person]),
    io:format("Result: ~p~n", [Result]),
    io:format("Error: ~p~n", [Error]),
    ok.

三、元组操作 #

3.1 获取大小 #

erlang
-module(tuple_size).
-export([demo/0]).

demo() ->
    Tuple = {a, b, c, d, e},
    Size = tuple_size(Tuple),
    io:format("Tuple: ~p~n", [Tuple]),
    io:format("Size: ~p~n", [Size]),
    ok.

3.2 访问元素 #

erlang
-module(tuple_access).
-export([demo/0]).

demo() ->
    Tuple = {a, b, c, d, e},
    
    First = element(1, Tuple),
    Third = element(3, Tuple),
    Last = element(tuple_size(Tuple), Tuple),
    
    io:format("Tuple: ~p~n", [Tuple]),
    io:format("First: ~p~n", [First]),
    io:format("Third: ~p~n", [Third]),
    io:format("Last: ~p~n", [Last]),
    ok.

注意:元素索引从1开始。

3.3 设置元素 #

erlang
-module(tuple_set).
-export([demo/0]).

demo() ->
    Tuple = {a, b, c},
    
    NewTuple = setelement(2, Tuple, x),
    
    io:format("Original: ~p~n", [Tuple]),
    io:format("Modified: ~p~n", [NewTuple]),
    ok.

3.4 元组与列表转换 #

erlang
-module(tuple_list_conv).
-export([demo/0]).

demo() ->
    Tuple = {a, b, c},
    List = tuple_to_list(Tuple),
    
    NewTuple = list_to_tuple([1, 2, 3, 4]),
    
    io:format("Tuple: ~p~n", [Tuple]),
    io:format("To list: ~p~n", [List]),
    io:format("From list: ~p~n", [NewTuple]),
    ok.

3.5 追加元素 #

erlang
-module(tuple_append).
-export([append/2]).

append(Tuple, Element) ->
    list_to_tuple(tuple_to_list(Tuple) ++ [Element]).

四、元组模式匹配 #

4.1 基本匹配 #

erlang
-module(tuple_match).
-export([demo/0]).

demo() ->
    {A, B, C} = {1, 2, 3},
    io:format("A=~p, B=~p, C=~p~n", [A, B, C]),
    
    {point, X, Y} = {point, 10, 20},
    io:format("X=~p, Y=~p~n", [X, Y]),
    ok.

4.2 部分匹配 #

erlang
-module(partial_match).
-export([demo/0]).

demo() ->
    {First, _, _} = {a, b, c},
    io:format("First: ~p~n", [First]),
    
    {_, Second, _} = {a, b, c},
    io:format("Second: ~p~n", [Second]),
    ok.

4.3 嵌套匹配 #

erlang
-module(nested_match).
-export([demo/0]).

demo() ->
    {A, {B, C}} = {1, {2, 3}},
    io:format("A=~p, B=~p, C=~p~n", [A, B, C]),
    
    {person, Name, {address, City, Country}} = 
        {person, "Alice", {address, "Beijing", "China"}},
    io:format("Name=~p, City=~p, Country=~p~n", [Name, City, Country]),
    ok.

4.4 函数参数匹配 #

erlang
-module(func_match).
-export([area/1, describe/1]).

area({rectangle, Width, Height}) -> Width * Height;
area({circle, Radius}) -> math:pi() * Radius * Radius;
area({square, Side}) -> Side * Side.

describe({point, X, Y}) ->
    io:format("Point at (~p, ~p)~n", [X, Y]);
describe({person, Name, Age}) ->
    io:format("~s is ~p years old~n", [Name, Age]).

五、常用元组模式 #

5.1 结果元组 #

erlang
-module(result_tuple).
-export([divide/2, safe_divide/2]).

divide(_, 0) -> {error, division_by_zero};
divide(A, B) -> {ok, A / B}.

safe_divide(A, B) ->
    case divide(A, B) of
        {ok, Result} -> {ok, Result};
        {error, Reason} -> {error, Reason}
    end.

5.2 状态元组 #

erlang
-module(state_tuple).
-export([init/0, update/2, get/1]).

init() -> {state, 0, []}.

update({state, Count, Items}, NewItem) ->
    {state, Count + 1, [NewItem | Items]}.

get({state, Count, Items}) ->
    #{count => Count, items => Items}.

5.3 配置元组 #

erlang
-module(config_tuple).
-export([get_config/0]).

get_config() ->
    {config, 
        {server, "localhost", 8080},
        {database, "localhost", 5432, "mydb"},
        {logging, debug, "/var/log/app.log"}
    }.

六、元组与记录 #

6.1 记录是元组的语法糖 #

erlang
-module(record_as_tuple).
-export([demo/0]).

-record(person, {name, age, city}).

demo() ->
    Person = #person{name = "Alice", age = 30, city = "Beijing"},
    io:format("Record: ~p~n", [Person]),
    
    {person, "Alice", 30, "Beijing"} = Person,
    io:format("As tuple: ~p~n", [Person]),
    ok.

6.2 使用记录的优势 #

erlang
-module(record_advantage).
-export([demo/0]).

-record(point, {x = 0, y = 0}).

demo() ->
    P1 = #point{},
    P2 = #point{x = 10},
    P3 = #point{x = 10, y = 20},
    
    io:format("P1: ~p~n", [P1]),
    io:format("P2: ~p~n", [P2]),
    io:format("P3: ~p~n", [P3]),
    
    io:format("P3.x: ~p~n", [P3#point.x]),
    io:format("P3.y: ~p~n", [P3#point.y]),
    ok.

七、元组操作函数 #

7.1 自定义函数 #

erlang
-module(tuple_utils).
-export([map/2, filter/2, foldl/3]).

map(Fun, Tuple) ->
    list_to_tuple(lists:map(Fun, tuple_to_list(Tuple))).

filter(Pred, Tuple) ->
    list_to_tuple(lists:filter(Pred, tuple_to_list(Tuple))).

foldl(Fun, Acc, Tuple) ->
    lists:foldl(Fun, Acc, tuple_to_list(Tuple)).

7.2 使用示例 #

erlang
-module(tuple_utils_demo).
-export([demo/0]).

demo() ->
    Tuple = {1, 2, 3, 4, 5},
    
    Doubled = tuple_utils:map(fun(X) -> X * 2 end, Tuple),
    Evens = tuple_utils:filter(fun(X) -> X rem 2 =:= 0 end, Tuple),
    Sum = tuple_utils:foldl(fun(X, Acc) -> X + Acc end, 0, Tuple),
    
    io:format("Original: ~p~n", [Tuple]),
    io:format("Doubled: ~p~n", [Doubled]),
    io:format("Evens: ~p~n", [Evens]),
    io:format("Sum: ~p~n", [Sum]),
    ok.

八、实际应用 #

8.1 表示复数 #

erlang
-module(complex).
-export([new/2, add/2, multiply/2, magnitude/1]).

new(Real, Imag) -> {complex, Real, Imag}.

add({complex, R1, I1}, {complex, R2, I2}) ->
    {complex, R1 + R2, I1 + I2}.

multiply({complex, R1, I1}, {complex, R2, I2}) ->
    {complex, R1 * R2 - I1 * I2, R1 * I2 + R2 * I1}.

magnitude({complex, R, I}) ->
    math:sqrt(R * R + I * I).

8.2 表示日期时间 #

erlang
-module(datetime_tuple).
-export([now/0, format/1]).

now() ->
    {Date, Time} = erlang:localtime(),
    {datetime, Date, Time}.

format({datetime, {Year, Month, Day}, {Hour, Min, Sec}}) ->
    io_lib:format("~p-~2..0B-~2..0B ~2..0B:~2..0B:~2..0B",
                  [Year, Month, Day, Hour, Min, Sec]).

8.3 HTTP响应 #

erlang
-module(http_response).
-export([ok/1, not_found/0, error/2]).

ok(Body) -> {ok, 200, Body}.

not_found() -> {error, 404, "Not Found"}.

error(Code, Message) -> {error, Code, Message}.

8.4 消息传递 #

erlang
-module(message_tuple).
-export([send/2, receive_msg/0]).

send(Pid, Type, Data) ->
    Pid ! {Type, self(), Data}.

receive_msg() ->
    receive
        {ping, From, _} ->
            From ! {pong, self(), ok},
            ok;
        {request, From, Data} ->
            Result = process(Data),
            From ! {response, self(), Result},
            ok;
        {stop, _From, _Reason} ->
            stopped
    end.

process(Data) -> {processed, Data}.

九、元组与列表比较 #

特性 元组 列表
大小 固定 可变
内存 连续 链式
访问 O(1) O(n)
添加元素 创建新元组 头部O(1)
适用场景 固定结构 动态集合
erlang
-module(tuple_vs_list).
-export([demo/0]).

demo() ->
    Tuple = {a, b, c},
    List = [a, b, c],
    
    io:format("Tuple element 2: ~p~n", [element(2, Tuple)]),
    io:format("List element 2: ~p~n", [lists:nth(2, List)]),
    ok.

十、总结 #

本章学习了:

  • 元组的定义和特点
  • 元组操作函数
  • 元组模式匹配
  • 常用元组模式
  • 元组与记录的关系
  • 自定义元组操作函数
  • 实际应用案例
  • 元组与列表的比较

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

最后更新:2026-03-27