Erlang函数基础 #

一、函数概述 #

函数是Erlang程序的基本构建块,每个函数都属于一个模块。

1.1 函数特点 #

  • 函数必须定义在模块中
  • 函数名是原子
  • 支持多子句
  • 支持模式匹配参数
  • 支持守卫条件

二、函数定义 #

2.1 基本语法 #

erlang
-module(basic_function).
-export([add/2, greet/1]).

add(A, B) -> A + B.

greet(Name) -> io:format("Hello, ~s!~n", [Name]).

2.2 函数导出 #

erlang
-module(export_demo).
-export([public_func/1]).
-export([another_public/2]).

public_func(X) -> X.
another_public(A, B) -> {A, B}.
private_func(X) -> X * 2.

2.3 export_all #

erlang
-module(export_all_demo).
-compile(export_all).

func1() -> ok.
func2() -> ok.

注意:仅用于开发调试,生产环境不建议使用。

三、多子句函数 #

3.1 基本多子句 #

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

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

3.2 模式匹配子句 #

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

process([]) -> empty;
process([H]) -> {one, H};
process([H1, H2]) -> {two, H1, H2};
process([H | T]) -> {many, H, T}.

3.3 子句顺序 #

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

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

注意:更具体的模式应该放在前面。

3.4 默认子句 #

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

handle({ok, Value}) -> {success, Value};
handle({error, Reason}) -> {failure, Reason};
handle(_) -> unknown.

四、函数参数 #

4.1 位置参数 #

erlang
-module(positional_args).
-export([create_user/3]).

create_user(Name, Age, Email) ->
    #{name => Name, age => Age, email => Email}.

4.2 模式匹配参数 #

erlang
-module(pattern_args).
-export([extract/1]).

extract({point, X, Y}) -> {x, X, y, Y};
extract({person, Name, Age}) -> {name, Name, age, Age};
extract(Other) -> {unknown, Other}.

4.3 嵌套模式参数 #

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

process({request, {header, Id}, {body, Data}}) ->
    #{id => Id, data => Data}.

4.4 忽略参数 #

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

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

五、守卫 #

5.1 基本守卫 #

erlang
-module(basic_guard).
-export([abs/1, max/2]).

abs(N) when N < 0 -> -N;
abs(N) -> N.

max(A, B) when A > B -> A;
max(_, B) -> B.

5.2 多条件守卫 #

erlang
-module(multi_guard).
-export([classify_age/1]).

classify_age(Age) when Age < 13 -> child;
classify_age(Age) when Age >= 13, Age < 20 -> teenager;
classify_age(Age) when Age >= 20, Age < 65 -> adult;
classify_age(Age) when Age >= 65 -> senior.

5.3 守卫序列 #

erlang
-module(guard_sequence).
-export([validate/1]).

validate(X) when is_integer(X), X > 0, X < 100 -> valid;
validate(X) when is_float(X) -> valid_float;
validate(_) -> invalid.

5.4 守卫函数 #

erlang
-module(guard_functions).
-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(X) when is_binary(X) -> binary;
process(X) when is_atom(X) -> atom;
process(_) -> other.

六、函数调用 #

6.1 本地调用 #

erlang
-module(local_call).
-export([outer/1]).

outer(X) ->
    Inner = inner(X),
    {outer, Inner}.

inner(X) -> {inner, X}.

6.2 模块调用 #

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

demo() ->
    Result = lists:map(fun(X) -> X * 2 end, [1, 2, 3]),
    io:format("Result: ~p~n", [Result]).

6.3 完全限定调用 #

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

demo() ->
    Result = my_module:my_function(42),
    {result, Result}.

my_function(X) -> X * 2.

6.4 动态模块调用 #

erlang
-module(dynamic_call).
-export([call/3]).

call(Module, Function, Args) ->
    apply(Module, Function, Args).

七、函数返回值 #

7.1 单一返回值 #

erlang
-module(single_return).
-export([double/1]).

double(X) -> X * 2.

7.2 元组返回值 #

erlang
-module(tuple_return).
-export([divide/2]).

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

7.3 多返回值处理 #

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

process(Data) ->
    case divide(Data, 2) of
        {ok, Result} -> {success, Result};
        {error, Reason} -> {failure, Reason}
    end.

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

八、函数文档 #

8.1 Edoc格式 #

erlang
-module(edoc_example).
-export([add/2, factorial/1]).

add(A, B) -> A + B.

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

8.2 模块文档 #

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

process(Data) -> Data.

九、函数规范 #

9.1 类型规范 #

erlang
-module(type_spec).
-export([add/2, greet/1]).

-spec add(number(), number()) -> number().
add(A, B) -> A + B.

-spec greet(string()) -> ok.
greet(Name) -> io:format("Hello, ~s!~n", [Name]).

9.2 复杂类型规范 #

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

-type result() :: {ok, term()} | {error, term()}.
-type input() :: integer() | float() | string().

-spec process(input()) -> result().
process(X) when is_number(X) -> {ok, X * 2};
process(X) when is_list(X) -> {ok, string:uppercase(X)};
process(_) -> {error, invalid_input}.

十、函数最佳实践 #

10.1 函数命名 #

erlang
-module(naming_practice).
-export([get_user_name/1, calculate_total_price/2, is_valid_email/1]).

get_user_name(User) -> maps:get(name, User).
calculate_total_price(Price, Quantity) -> Price * Quantity.
is_valid_email(Email) -> string:find(Email, "@") =/= nomatch.

命名规范:

  • 使用小写字母和下划线
  • 动词开头表示动作
  • 布尔函数以 is_ 开头
  • 名称要有意义

10.2 函数长度 #

erlang
-module(function_length).
-export([good/1, bad/1]).

good(Data) ->
    Validated = validate(Data),
    Transformed = transform(Validated),
    save(Transformed).

bad(Data) ->
    validate(Data),
    transform(Data),
    save(Data).

validate(D) -> D.
transform(D) -> D.
save(D) -> D.

10.3 单一职责 #

erlang
-module(single_responsibility).
-export([process_user/1]).

process_user(Data) ->
    User = create_user(Data),
    validate_user(User),
    save_user(User),
    {ok, User}.

create_user(Data) -> Data.
validate_user(_User) -> ok.
save_user(_User) -> ok.

10.4 避免深层嵌套 #

erlang
-module(avoid_nesting).
-export([good/1, bad/1]).

bad(Data) ->
    case step1(Data) of
        {ok, R1} ->
            case step2(R1) of
                {ok, R2} ->
                    case step3(R2) of
                        {ok, R3} -> {ok, R3};
                        {error, E} -> {error, E}
                    end;
                {error, E} -> {error, E}
            end;
        {error, E} -> {error, E}
    end.

good(Data) ->
    with(Data, [
        fun step1/1,
        fun step2/1,
        fun step3/1
    ]).

with({error, _} = Error, _) -> Error;
with({ok, Value}, [Fun | Rest]) -> with(Fun({ok, Value}), Rest);
with({ok, Value}, []) -> {ok, Value}.

step1(D) -> {ok, D}.
step2(D) -> {ok, D}.
step3(D) -> {ok, D}.

十一、总结 #

本章学习了:

  • 函数定义语法
  • 多子句函数
  • 函数参数
  • 守卫表达式
  • 函数调用方式
  • 函数返回值
  • 函数文档和规范
  • 最佳实践

准备好学习递归函数了吗?让我们进入下一章。

最后更新:2026-03-27