Erlang复杂模式匹配 #
一、嵌套模式匹配 #
1.1 嵌套元组 #
erlang
-module(nested_tuple).
-export([extract/1]).
extract({person, Name, {address, {city, City}, {country, Country}}}) ->
#{name => Name, city => City, country => Country}.
1.2 嵌套列表 #
erlang
-module(nested_list).
-export([process/1]).
process([[H1 | _], [H2 | _] | _]) ->
{first_heads, H1, H2};
process([Single | _]) ->
{single, Single};
process([]) ->
empty.
1.3 混合嵌套 #
erlang
-module(mixed_nested).
-export([handle/1]).
handle({request,
{header, Id, Version},
{body, {type, Type}, Data}}) ->
#{id => Id, version => Version, type => Type, data => Data}.
二、复杂守卫 #
2.1 多条件守卫 #
erlang
-module(multi_guard).
-export([classify/1]).
classify({point, X, Y})
when X > 0, Y > 0 -> first_quadrant;
classify({point, X, Y})
when X < 0, Y > 0 -> second_quadrant;
classify({point, X, Y})
when X < 0, Y < 0 -> third_quadrant;
classify({point, X, Y})
when X > 0, Y < 0 -> fourth_quadrant;
classify({point, 0, 0}) -> origin;
classify({point, _, 0}) -> x_axis;
classify({point, 0, _}) -> y_axis.
2.2 守卫中的orelse #
erlang
-module(guard_orelse).
-export([is_weekend/1]).
is_weekend(Day) when Day =:= saturday; Day =:= sunday -> true;
is_weekend(_) -> false.
2.3 复杂守卫表达式 #
erlang
-module(complex_guard).
-export([validate_user/1]).
-record(user, {name, age, role}).
validate_user(#user{name = Name, age = Age, role = Role})
when is_list(Name), length(Name) > 0,
Age >= 18, Age =< 120,
Role =:= admin orelse Role =:= user ->
valid;
validate_user(_) ->
invalid.
2.4 守卫函数组合 #
erlang
-module(guard_combine).
-export([process/2]).
process(List, N)
when is_list(List), length(List) >= N, N > 0 ->
lists:sublist(List, N);
process(_, _) ->
{error, invalid_args}.
三、列表模式进阶 #
3.1 特定长度列表 #
erlang
-module(list_length_pattern).
-export([process/1]).
process([]) -> empty;
process([A]) -> one(A);
process([A, B]) -> two(A, B);
process([A, B, C]) -> three(A, B, C);
process([_, _, _ | _]) -> many.
3.2 前缀匹配 #
erlang
-module(prefix_match).
-export([check/2]).
check([], _) -> true;
check([H | T1], [H | T2]) -> check(T1, T2);
check(_, _) -> false.
3.3 后缀匹配 #
erlang
-module(suffix_match).
-export([ends_with/2]).
ends_with(Suffix, List) ->
ends_with(lists:reverse(Suffix), lists:reverse(List)).
ends_with([], _) -> true;
ends_with([H | T1], [H | T2]) -> ends_with(T1, T2);
ends_with(_, _) -> false.
3.4 分割列表 #
erlang
-module(split_pattern).
-export([split_at/2]).
split_at(N, List) -> split_at(N, List, []).
split_at(0, List, Acc) -> {lists:reverse(Acc), List};
split_at(_, [], Acc) -> {lists:reverse(Acc), []};
split_at(N, [H | T], Acc) -> split_at(N - 1, T, [H | Acc]).
四、二进制模式进阶 #
4.1 协议解析 #
erlang
-module(protocol_parse).
-export([parse_header/1]).
parse_header(<<Version:4, IHL:4, ToS:8, TotalLength:16,
Identification:16, Flags:3, FragmentOffset:13,
TTL:8, Protocol:8, HeaderChecksum:16,
SourceIP:32, DestIP:32, Rest/binary>>) ->
#{version => Version,
ihl => IHL,
tos => ToS,
total_length => TotalLength,
identification => Identification,
flags => Flags,
fragment_offset => FragmentOffset,
ttl => TTL,
protocol => Protocol,
checksum => HeaderChecksum,
source_ip => format_ip(SourceIP),
dest_ip => format_ip(DestIP),
payload => Rest}.
format_ip(IP) ->
<<A, B, C, D>> = <<IP:32>>,
io_lib:format("~p.~p.~p.~p", [A, B, C, D]).
4.2 变长字段 #
erlang
-module(varlen_field).
-export([parse_message/1]).
parse_message(<<Type:8, Length:16, Data:Length/binary, Rest/binary>>) ->
#{type => Type, data => Data, rest => Rest};
parse_message(<<Type:8, 0:16>>) ->
#{type => Type, data => <<>>, rest => <<>>}.
4.3 位级解析 #
erlang
-module(bit_level_parse).
-export([parse_flags/1]).
parse_flags(<<_:5, Urg:1, Ack:1, Psh:1, Rst:1, Syn:1, Fin:1>>) ->
#{urg => Urg =:= 1,
ack => Ack =:= 1,
psh => Psh =:= 1,
rst => Rst =:= 1,
syn => Syn =:= 1,
fin => Fin =:= 1}.
五、映射模式进阶 #
5.1 部分匹配 #
erlang
-module(map_partial).
-export([handle/1]).
handle(#{type := user, name := Name}) ->
{user, Name};
handle(#{type := admin, name := Name, level := Level}) ->
{admin, Name, Level};
handle(#{type := Type}) ->
{unknown, Type}.
5.2 嵌套映射 #
erlang
-module(nested_map).
-export([extract/1]).
extract(#{user := #{name := Name, address := #{city := City}}}) ->
#{name => Name, city => City}.
5.3 可选字段 #
erlang
-module(optional_field).
-export([process/1]).
process(#{name := Name, email := Email}) ->
{full, Name, Email};
process(#{name := Name}) ->
{partial, Name};
process(_) ->
unknown.
六、函数子句模式 #
6.1 多参数模式 #
erlang
-module(multi_arg_pattern).
-export([process/2]).
process([], _) -> empty_list;
process(_, []) -> empty_second;
process([H1 | _], [H2 | _]) when H1 > H2 -> first_larger;
process([H1 | _], [H2 | _]) when H1 < H2 -> second_larger;
process([H | _], [H | _]) -> equal_heads.
6.2 记录模式 #
erlang
-module(record_pattern).
-export([handle/1]).
-record(user, {name, role = guest}).
handle(#user{role = admin}) -> administrator;
handle(#user{role = moderator}) -> moderator;
handle(#user{role = guest}) -> guest.
6.3 复杂函数头 #
erlang
-module(complex_func_head).
-export([route/3]).
route(get, "/users", _Params) -> list_users;
route(get, ["/users", Id], _Params) -> get_user(Id);
route(post, "/users", Params) -> create_user(Params);
route(put, ["/users", Id], Params) -> update_user(Id, Params);
route(delete, ["/users", Id], _Params) -> delete_user(Id);
route(_, _, _) -> not_found.
list_users() -> ok.
get_user(_Id) -> ok.
create_user(_Params) -> ok.
update_user(_Id, _Params) -> ok.
delete_user(_Id) -> ok.
七、case表达式模式 #
7.1 复杂case #
erlang
-module(complex_case).
-export([process/1]).
process(Data) ->
case Data of
{ok, {result, Value}} when Value > 0 ->
{positive, Value};
{ok, {result, Value}} when Value < 0 ->
{negative, Value};
{ok, {result, 0}} ->
zero;
{error, {validation, Field}} ->
{validation_error, Field};
{error, Reason} ->
{error, Reason};
_ ->
unknown
end.
7.2 嵌套case #
erlang
-module(nested_case).
-export([process/1]).
process({request, Type, Data}) ->
case Type of
create ->
case validate(Data) of
ok -> create_resource(Data);
{error, Reason} -> {error, Reason}
end;
update ->
case find(Data) of
{ok, Resource} -> update_resource(Resource, Data);
{error, Reason} -> {error, Reason}
end;
delete ->
delete_resource(Data)
end.
validate(_) -> ok.
find(_) -> {ok, resource}.
create_resource(_) -> ok.
update_resource(_, _) -> ok.
delete_resource(_) -> ok.
八、receive模式 #
8.1 选择性接收 #
erlang
-module(selective_receive).
-export([collect/2]).
collect(0, Acc) -> lists:reverse(Acc);
collect(N, Acc) ->
receive
{data, Value} ->
collect(N - 1, [Value | Acc]);
{error, _Reason} ->
collect(N, Acc)
after 5000 ->
timeout
end.
8.2 模式优先级 #
erlang
-module(receive_priority).
-export([loop/0]).
loop() ->
receive
{urgent, Msg} ->
handle_urgent(Msg),
loop();
{normal, Msg} ->
handle_normal(Msg),
loop();
{low, Msg} ->
handle_low(Msg),
loop()
end.
handle_urgent(Msg) -> io:format("Urgent: ~p~n", [Msg]).
handle_normal(Msg) -> io:format("Normal: ~p~n", [Msg]).
handle_low(Msg) -> io:format("Low: ~p~n", [Msg]).
8.3 超时处理 #
erlang
-module(timeout_receive).
-export([request/2]).
request(Pid, Msg) ->
Ref = make_ref(),
Pid ! {request, self(), Ref, Msg},
receive
{response, Ref, Result} -> {ok, Result}
after 5000 ->
{error, timeout}
end.
九、实际应用案例 #
9.1 JSON解析 #
erlang
-module(json_pattern).
-export([extract/2]).
extract(Key, {struct, Props}) when is_list(Props) ->
case proplists:get_value(Key, Props) of
undefined -> undefined;
Value -> extract_value(Value)
end;
extract(Key, {array, Items}) when is_list(Items) ->
[extract(Key, Item) || Item <- Items];
extract(_, _) ->
undefined.
extract_value({struct, Props}) -> {struct, Props};
extract_value({array, Items}) -> {array, Items};
extract_value(Value) -> Value.
9.2 HTTP路由 #
erlang
-module(http_router).
-export([route/1]).
route(#{method := get, path := "/"}) ->
index;
route(#{method := get, path := "/users"}) ->
list_users;
route(#{method := get, path := "/users/" ++ Id}) ->
{get_user, Id};
route(#{method := post, path := "/users", body := Body}) ->
{create_user, Body};
route(#{method := Method, path := Path}) ->
{not_found, Method, Path}.
9.3 消息协议 #
erlang
-module(message_protocol).
-export([encode/1, decode/1]).
encode({ping, Id}) ->
<<1:8, Id:32>>;
encode({pong, Id}) ->
<<2:8, Id:32>>;
encode({data, Id, Data}) when is_binary(Data) ->
Length = byte_size(Data),
<<3:8, Id:32, Length:16, Data/binary>>;
encode({error, Id, Code, Msg}) when is_binary(Msg) ->
Length = byte_size(Msg),
<<4:8, Id:32, Code:16, Length:8, Msg/binary>>.
decode(<<1:8, Id:32>>) ->
{ping, Id};
decode(<<2:8, Id:32>>) ->
{pong, Id};
decode(<<3:8, Id:32, Length:16, Data:Length/binary>>) ->
{data, Id, Data};
decode(<<4:8, Id:32, Code:16, Length:8, Msg:Length/binary>>) ->
{error, Id, Code, Msg}.
9.4 状态机 #
erlang
-module(state_machine).
-export([start/0, event/2]).
start() -> idle.
event(idle, connect) -> connected;
event(connected, disconnect) -> idle;
event(connected, {send, Data}) ->
io:format("Sending: ~p~n", [Data]),
connected;
event(State, _Event) -> State.
十、模式匹配最佳实践 #
10.1 保持模式简单 #
erlang
-module(simple_pattern).
-export([good/1, bad/1]).
good({ok, Value}) -> Value;
good({error, Reason}) -> {error, Reason}.
bad({ok, {nested, {deep, {value, Value}}}}) -> Value.
10.2 使用辅助函数 #
erlang
-module(helper_func).
-export([process/1]).
process(Data) ->
case extract_info(Data) of
{ok, Info} -> handle_info(Info);
{error, Reason} -> {error, Reason}
end.
extract_info({type_a, Value}) -> {ok, {a, Value}};
extract_info({type_b, Value}) -> {ok, {b, Value}};
extract_info(_) -> {error, unknown_type}.
handle_info({a, Value}) -> {processed_a, Value};
handle_info({b, Value}) -> {processed_b, Value}.
10.3 使用记录提高可读性 #
erlang
-module(record_readability).
-export([process/1]).
-record(request, {type, id, data}).
process(#request{type = create, id = Id, data = Data}) ->
{create, Id, Data};
process(#request{type = update, id = Id, data = Data}) ->
{update, Id, Data};
process(#request{type = delete, id = Id}) ->
{delete, Id}.
十一、总结 #
本章学习了:
- 嵌套模式匹配
- 复杂守卫表达式
- 列表模式进阶
- 二进制模式进阶
- 映射模式进阶
- 函数子句模式
- case和receive模式
- 实际应用案例
- 最佳实践
准备好学习控制流了吗?让我们进入下一章。
最后更新:2026-03-27