Erlang递归函数 #
一、递归基础回顾 #
1.1 递归结构 #
erlang
-module(recursion_review).
-export([factorial/1]).
factorial(0) -> 1;
factorial(N) when N > 0 -> N * factorial(N - 1).
1.2 递归要素 #
- 基准条件(Base Case)
- 递归条件(Recursive Case)
- 收敛性(Convergence)
二、尾递归优化 #
2.1 非尾递归 #
erlang
-module(non_tail).
-export([sum/1, length/1]).
sum([]) -> 0;
sum([H | T]) -> H + sum(T).
length([]) -> 0;
length([_ | T]) -> 1 + length(T).
2.2 尾递归版本 #
erlang
-module(tail_recursive).
-export([sum/1, length/1]).
sum(List) -> sum(List, 0).
sum([], Acc) -> Acc;
sum([H | T], Acc) -> sum(T, H + Acc).
length(List) -> length(List, 0).
length([], Acc) -> Acc;
length([_ | T], Acc) -> length(T, Acc + 1).
2.3 尾递归原理 #
尾递归调用是函数的最后操作,编译器可以优化为循环:
erlang
-module(tail_principle).
-export([count_down/1]).
count_down(N) -> count_down(N, []).
count_down(0, Acc) -> Acc;
count_down(N, Acc) when N > 0 -> count_down(N - 1, [N | Acc]).
三、累加器模式 #
3.1 基本累加器 #
erlang
-module(accumulator_basic).
-export([reverse/1, sum/1]).
reverse(List) -> reverse(List, []).
reverse([], Acc) -> Acc;
reverse([H | T], Acc) -> reverse(T, [H | Acc]).
sum(List) -> sum(List, 0).
sum([], Acc) -> Acc;
sum([H | T], Acc) -> sum(T, H + Acc).
3.2 多累加器 #
erlang
-module(multi_accumulator).
-export([partition/2, split_at/2]).
partition(Pred, List) -> partition(Pred, List, [], []).
partition(_, [], TrueAcc, FalseAcc) ->
{lists:reverse(TrueAcc), lists:reverse(FalseAcc)};
partition(Pred, [H | T], TrueAcc, FalseAcc) ->
case Pred(H) of
true -> partition(Pred, T, [H | TrueAcc], FalseAcc);
false -> partition(Pred, T, TrueAcc, [H | FalseAcc])
end.
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]).
3.3 复杂累加器 #
erlang
-module(complex_accumulator).
-export([group_by/2]).
group_by(KeyFun, List) ->
Result = group_by(KeyFun, List, #{}),
maps:map(fun(_, V) -> lists:reverse(V) end, Result).
group_by(_, [], Acc) -> Acc;
group_by(KeyFun, [H | T], Acc) ->
Key = KeyFun(H),
Current = maps:get(Key, Acc, []),
group_by(KeyFun, T, Acc#{Key => [H | Current]}).
四、递归数据结构 #
4.1 列表处理 #
erlang
-module(list_recursion).
-export([map/2, filter/2, foldl/3, foldr/3]).
map(_, []) -> [];
map(Fun, [H | T]) -> [Fun(H) | map(Fun, T)].
filter(_, []) -> [];
filter(Pred, [H | T]) ->
case Pred(H) of
true -> [H | filter(Pred, T)];
false -> filter(Pred, T)
end.
foldl(_, Acc, []) -> Acc;
foldl(Fun, Acc, [H | T]) -> foldl(Fun, Fun(H, Acc), T).
foldr(_, Acc, []) -> Acc;
foldr(Fun, Acc, [H | T]) -> Fun(H, foldr(Fun, Acc, T)).
4.2 树处理 #
erlang
-module(tree_recursion).
-export([sum/1, map/2, find/2]).
sum({node, Value, Left, Right}) ->
Value + sum(Left) + sum(Right);
sum(empty) -> 0.
map(Fun, {node, Value, Left, Right}) ->
{node, Fun(Value), map(Fun, Left), map(Fun, Right)};
map(_Fun, empty) -> empty.
find(Pred, {node, Value, Left, Right}) ->
case Pred(Value) of
true -> {found, Value};
false ->
case find(Pred, Left) of
{found, _} = Result -> Result;
not_found -> find(Pred, Right)
end
end;
find(_Pred, empty) -> not_found.
4.3 嵌套列表处理 #
erlang
-module(nested_list).
-export([flatten/1, deep_map/2]).
flatten(List) -> flatten(List, []).
flatten([], Acc) -> Acc;
flatten([H | T], Acc) when is_list(H) ->
flatten(T, flatten(H, Acc));
flatten([H | T], Acc) ->
flatten(T, [H | Acc]).
deep_map(Fun, List) when is_list(List) ->
[deep_map(Fun, Item) || Item <- List];
deep_map(Fun, Item) ->
Fun(Item).
五、递归模式 #
5.1 线性递归 #
erlang
-module(linear_recursion).
-export([factorial/1, fibonacci/1]).
factorial(0) -> 1;
factorial(N) when N > 0 -> N * factorial(N - 1).
fibonacci(0) -> 0;
fibonacci(1) -> 1;
fibonacci(N) when N > 1 -> fibonacci(N - 1) + fibonacci(N - 2).
5.2 尾递归 #
erlang
-module(tail_recursion).
-export([factorial/1, fibonacci/1]).
factorial(N) -> factorial(N, 1).
factorial(0, Acc) -> Acc;
factorial(N, Acc) when N > 0 -> factorial(N - 1, N * Acc).
fibonacci(N) -> fibonacci(N, 0, 1).
fibonacci(0, A, _B) -> A;
fibonacci(N, A, B) when N > 0 -> fibonacci(N - 1, B, A + B).
5.3 相互递归 #
erlang
-module(mutual_recursion).
-export([is_even/1, is_odd/1]).
is_even(0) -> true;
is_even(N) when N > 0 -> is_odd(N - 1).
is_odd(0) -> false;
is_odd(N) when N > 0 -> is_even(N - 1).
5.4 分治递归 #
erlang
-module(divide_conquer).
-export([merge_sort/1, quick_sort/1]).
merge_sort([]) -> [];
merge_sort([X]) -> [X];
merge_sort(List) ->
{Left, Right} = split(List),
merge(merge_sort(Left), merge_sort(Right)).
split(List) -> split(List, [], []).
split([], Left, Right) -> {Left, Right};
split([H | T], Left, Right) -> split(T, [H | Right], Left).
merge([], Right) -> Right;
merge(Left, []) -> Left;
merge([H1 | T1] = Left, [H2 | T2] = Right) ->
if
H1 =< H2 -> [H1 | merge(T1, Right)];
true -> [H2 | merge(Left, T2)]
end.
quick_sort([]) -> [];
quick_sort([Pivot | Rest]) ->
{Smaller, Larger} = partition(Pivot, Rest),
quick_sort(Smaller) ++ [Pivot] ++ quick_sort(Larger).
partition(Pivot, List) -> partition(Pivot, List, [], []).
partition(_, [], Smaller, Larger) -> {Smaller, Larger};
partition(Pivot, [H | T], Smaller, Larger) ->
if
H =< Pivot -> partition(Pivot, T, [H | Smaller], Larger);
true -> partition(Pivot, T, Smaller, [H | Larger])
end.
六、递归与状态 #
6.1 状态传递 #
erlang
-module(state_recursion).
-export([process_list/2]).
process_list([], State) -> {done, State};
process_list([H | T], State) ->
NewState = process_item(H, State),
process_list(T, NewState).
process_item(Item, State) ->
maps:update_with(count, fun(C) -> C + 1 end, 1, State).
6.2 服务循环 #
erlang
-module(service_loop).
-export([start/0, loop/1]).
start() ->
InitialState = #{count => 0},
spawn(fun() -> loop(InitialState) end).
loop(State) ->
receive
{increment, N} ->
NewState = maps:update_with(count, fun(C) -> C + N end, State),
loop(NewState);
{get_count, From} ->
Count = maps:get(count, State, 0),
From ! {count, Count},
loop(State);
stop ->
ok
end.
七、递归性能 #
7.1 栈深度 #
erlang
-module(stack_depth).
-export([bad/1, good/1]).
bad(0) -> done;
bad(N) -> bad(N - 1), ok.
good(0) -> done;
good(N) -> good(N - 1).
7.2 内存使用 #
erlang
-module(memory_usage).
-export([bad_sum/1, good_sum/1]).
bad_sum([]) -> 0;
bad_sum([H | T]) -> H + bad_sum(T).
good_sum(List) -> good_sum(List, 0).
good_sum([], Acc) -> Acc;
good_sum([H | T], Acc) -> good_sum(T, H + Acc).
7.3 优化技巧 #
erlang
-module(optimization).
-export([process_large_list/1]).
process_large_list(List) ->
process_large_list(List, [], 0).
process_large_list([], Acc, Count) ->
{lists:reverse(Acc), Count};
process_large_list([H | T], Acc, Count) ->
NewH = process_item(H),
process_large_list(T, [NewH | Acc], Count + 1).
process_item(X) -> X * 2.
八、实际应用 #
8.1 解析器 #
erlang
-module(parser).
-export([parse_tokens/1]).
parse_tokens(Tokens) -> parse_tokens(Tokens, []).
parse_tokens([], Acc) -> {ok, lists:reverse(Acc)};
parse_tokens([{error, _} = Error | _], _Acc) -> {error, Error};
parse_tokens([Token | Rest], Acc) ->
Parsed = parse_token(Token),
parse_tokens(Rest, [Parsed | Acc]).
parse_token({int, V}) -> {integer, V};
parse_token({str, V}) -> {string, V};
parse_token({atom, V}) -> {atom, V}.
8.2 文件处理 #
erlang
-module(file_processor).
-export([process_lines/1]).
process_lines(Path) ->
{ok, File} = file:open(Path, [read]),
try
process_lines(File, [])
after
file:close(File)
end.
process_lines(File, Acc) ->
case io:get_line(File, "") of
eof -> {ok, lists:reverse(Acc)};
{error, Reason} -> {error, Reason};
Line ->
Processed = process_line(Line),
process_lines(File, [Processed | Acc])
end.
process_line(Line) -> string:trim(Line).
8.3 树遍历 #
erlang
-module(tree_walker).
-export([preorder/1, inorder/1, postorder/1]).
preorder({node, Value, Left, Right}) ->
[Value | preorder(Left) ++ preorder(Right)];
preorder(empty) -> [].
inorder({node, Value, Left, Right}) ->
inorder(Left) ++ [Value] ++ inorder(Right);
inorder(empty) -> [].
postorder({node, Value, Left, Right}) ->
postorder(Left) ++ postorder(Right) ++ [Value];
postorder(empty) -> [].
九、总结 #
本章学习了:
- 尾递归优化
- 累加器模式
- 递归数据结构处理
- 递归模式
- 递归与状态
- 性能优化
- 实际应用
准备好学习高阶函数了吗?让我们进入下一章。
最后更新:2026-03-27