Erlang模式匹配基础 #

一、模式匹配概述 #

模式匹配是Erlang的核心特性之一,用于将模式与数据进行匹配,并从中提取信息。

1.1 模式匹配的作用 #

  • 变量绑定
  • 数据解构
  • 条件判断
  • 函数分派

1.2 匹配操作符 #

Erlang使用 = 作为匹配操作符:

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

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

注意= 不是赋值,而是模式匹配!

二、基本模式匹配 #

2.1 变量匹配 #

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

demo() ->
    X = 10,
    10 = X,
    
    io:format("X = ~p~n", [X]),
    ok.

2.2 单次赋值 #

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

demo() ->
    X = 10,
    io:format("X = ~p~n", [X]),
    ok.

2.3 匹配失败 #

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

demo() ->
    X = 10,
    try
        20 = X
    catch
        error:badmatch ->
            io:format("Match failed!~n")
    end,
    ok.

三、原子模式 #

3.1 精确匹配 #

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

demo() ->
    ok = ok,
    error = error,
    
    io:format("Atom match succeeded~n"),
    ok.

3.2 函数返回值匹配 #

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

demo() ->
    {ok, Result} = some_function(),
    io:format("Result: ~p~n", [Result]),
    ok.

some_function() -> {ok, 42}.

3.3 错误处理模式 #

erlang
-module(error_pattern).
-export([handle/1]).

handle({ok, Data}) ->
    io:format("Success: ~p~n", [Data]);
handle({error, Reason}) ->
    io:format("Error: ~p~n", [Reason]).

四、元组模式 #

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(nested_tuple_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}} = 
        {person, "Alice", {address, "Beijing"}},
    io:format("Name=~p, City=~p~n", [Name, City]),
    ok.

4.3 忽略部分 #

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

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

五、列表模式 #

5.1 头尾模式 #

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

demo() ->
    [H | T] = [1, 2, 3, 4, 5],
    io:format("Head=~p, Tail=~p~n", [H, T]),
    ok.

5.2 多元素模式 #

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

demo() ->
    [A, B, C | Rest] = [1, 2, 3, 4, 5],
    io:format("A=~p, B=~p, C=~p, Rest=~p~n", [A, B, C, Rest]),
    
    [First, Second] = [a, b],
    io:format("First=~p, Second=~p~n", [First, Second]),
    ok.

5.3 空列表模式 #

erlang
-module(empty_list_match).
-export([process/1]).

process([]) -> empty;
process([H | T]) -> {non_empty, H, T}.

5.4 特定元素匹配 #

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

demo() ->
    [1, 2, 3] = [1, 2, 3],
    
    [a, B, c] = [a, b, c],
    io:format("B = ~p~n", [B]),
    ok.

六、二进制模式 #

6.1 基本二进制匹配 #

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

demo() ->
    <<A, B, C>> = <<1, 2, 3>>,
    io:format("A=~p, B=~p, C=~p~n", [A, B, C]),
    ok.

6.2 固定位宽匹配 #

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

demo() ->
    <<Int:16>> = <<1, 2>>,
    io:format("16-bit int: ~p~n", [Int]),
    
    <<X:4, Y:4>> = <<16#AB:8>>,
    io:format("X=~p, Y=~p~n", [X, Y]),
    ok.

6.3 变长匹配 #

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

demo() ->
    <<Head:8, Rest/binary>> = <<1, 2, 3, 4, 5>>,
    io:format("Head=~p, Rest=~p~n", [Head, Rest]),
    ok.

七、映射模式 #

7.1 键值匹配 #

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

demo() ->
    #{a := A, b := B} = #{a => 1, b => 2, c => 3},
    io:format("A=~p, B=~p~n", [A, B]),
    ok.

7.2 函数参数匹配 #

erlang
-module(map_func_match).
-export([process/1]).

process(#{name := Name, age := Age}) ->
    io:format("Name: ~s, Age: ~p~n", [Name, Age]);
process(#{name := Name}) ->
    io:format("Name: ~s (age unknown)~n", [Name]);
process(_) ->
    io:format("Unknown~n").

八、守卫 #

8.1 基本守卫 #

erlang
-module(guard_basic).
-export([classify/1]).

classify(N) when N > 0 -> positive;
classify(N) when N < 0 -> negative;
classify(0) -> zero.

8.2 守卫序列 #

erlang
-module(guard_seq).
-export([demo/1]).

demo(N) when N > 0, N < 10 -> small;
demo(N) when N >= 10, N < 100 -> medium;
demo(N) when N >= 100 -> large.

8.3 守卫中的函数 #

erlang
-module(guard_func).
-export([process/1]).

process(X) when is_integer(X) -> integer;
process(X) when is_float(X) -> float;
process(X) when is_list(X) -> list;
process(X) when is_tuple(X) -> tuple;
process(_) -> other.

8.4 守卫限制 #

守卫中只能使用特定函数:

erlang
-module(guard_limit).
-export([valid/1, invalid/1]).

valid(X) when is_integer(X), X > 0 -> ok.

invalid(X) when my_func(X) -> ok.

允许的函数:

  • 类型检测:is_atom/1, is_integer/1, is_list/1
  • 比较:=:=, =/=, <, >, =<, >=
  • 算术:+, -, *, div, rem
  • 位运算:band, bor, bnot, bsl, bsr
  • 其他:abs/1, length/1, hd/1, tl/1, element/2

九、模式匹配应用 #

9.1 函数子句 #

erlang
-module(func_clause).
-export([factorial/1, fib/1]).

factorial(0) -> 1;
factorial(N) when N > 0 -> N * factorial(N - 1).

fib(0) -> 0;
fib(1) -> 1;
fib(N) when N > 1 -> fib(N - 1) + fib(N - 2).

9.2 case表达式 #

erlang
-module(case_expr).
-export([classify/1]).

classify(Value) ->
    case Value of
        {ok, Result} -> {success, Result};
        {error, Reason} -> {failure, Reason};
        _ -> unknown
    end.

9.3 receive匹配 #

erlang
-module(receive_match).
-export([loop/0]).

loop() ->
    receive
        {ping, From} ->
            From ! pong,
            loop();
        {stop, Reason} ->
            io:format("Stopping: ~p~n", [Reason]),
            stopped;
        Other ->
            io:format("Unknown message: ~p~n", [Other]),
            loop()
    end.

9.4 消息处理 #

erlang
-module(message_handling).
-export([handle/1]).

handle({request, Id, Data}) ->
    io:format("Request ~p: ~p~n", [Id, Data]),
    {response, Id, processed};
handle({response, Id, Result}) ->
    io:format("Response ~p: ~p~n", [Id, Result]),
    ok;
handle({error, Reason}) ->
    io:format("Error: ~p~n", [Reason]),
    error.

十、模式匹配技巧 #

10.1 使用_忽略 #

erlang
-module(ignore_pattern).
-export([first/1, second/1]).

first([H | _]) -> H.
second([_, H | _]) -> H.

10.2 使用带名忽略 #

erlang
-module(named_ignore).
-export([process/1]).

process({tag, _Value = Value}) ->
    io:format("Value: ~p~n", [Value]),
    Value.

10.3 模式匹配顺序 #

erlang
-module(match_order).
-export([process/1]).

process({specific, Value}) ->
    {specific, Value};
process({specific, _, _}) ->
    specific_tuple;
process({specific, _, _, _}) ->
    specific_triple;
process({specific, _}) ->
    specific_single;
process(_) ->
    other.

十一、总结 #

本章学习了:

  • 模式匹配的概念
  • 匹配操作符
  • 原子、元组、列表、二进制、映射模式
  • 守卫表达式
  • 模式匹配应用
  • 模式匹配技巧

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

最后更新:2026-03-27