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