Erlang条件语句 #
一、if表达式 #
1.1 基本语法 #
erlang
-module(if_basic).
-export([classify/1]).
classify(N) ->
if
N > 0 -> positive;
N < 0 -> negative;
true -> zero
end.
1.2 多条件 #
erlang
-module(if_multi).
-export([grade/1]).
grade(Score) ->
if
Score >= 90 -> 'A';
Score >= 80 -> 'B';
Score >= 70 -> 'C';
Score >= 60 -> 'D';
true -> 'F'
end.
1.3 守卫条件 #
erlang
-module(if_guard).
-export([process/1]).
process(X) ->
if
is_integer(X), X > 0 -> positive_integer;
is_integer(X), X < 0 -> negative_integer;
is_float(X) -> float_number;
is_list(X) -> list_value;
true -> other
end.
1.4 必须有true分支 #
erlang
-module(if_true).
-export([safe_classify/1]).
safe_classify(N) ->
if
N > 0 -> positive;
N < 0 -> negative;
true -> zero_or_other
end.
注意:if表达式必须有至少一个守卫为true,否则会抛出错误。
二、case表达式 #
2.1 基本语法 #
erlang
-module(case_basic).
-export([classify/1]).
classify(Value) ->
case Value of
{ok, Result} -> {success, Result};
{error, Reason} -> {failure, Reason};
_ -> unknown
end.
2.2 模式匹配 #
erlang
-module(case_pattern).
-export([handle/1]).
handle({point, X, Y}) ->
case {X, Y} of
{0, 0} -> origin;
{_, 0} -> x_axis;
{0, _} -> y_axis;
_ when X > 0, Y > 0 -> first_quadrant;
_ when X < 0, Y > 0 -> second_quadrant;
_ when X < 0, Y < 0 -> third_quadrant;
_ -> fourth_quadrant
end.
2.3 带守卫的case #
erlang
-module(case_guard).
-export([process/1]).
process(List) ->
case List of
[] -> empty;
[Single] -> {one, Single};
[A, B] when A > B -> {two, A, B, first_larger};
[A, B] -> {two, A, B, second_larger_or_equal};
[H | T] when length(T) > 5 -> {many, H, long_tail};
[H | T] -> {many, H, short_tail}
end.
2.4 嵌套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.
2.5 case返回值 #
erlang
-module(case_return).
-export([format_result/1]).
format_result(Result) ->
Formatted = case Result of
{ok, Value} -> io_lib:format("Success: ~p", [Value]);
{error, Reason} -> io_lib:format("Error: ~p", [Reason])
end,
lists:flatten(Formatted).
三、函数子句 vs case #
3.1 使用函数子句 #
erlang
-module(func_clause).
-export([handle/1]).
handle({ok, Result}) -> {success, Result};
handle({error, Reason}) -> {failure, Reason};
handle(_) -> unknown.
3.2 使用case #
erlang
-module(use_case).
-export([handle/1]).
handle(Value) ->
case Value of
{ok, Result} -> {success, Result};
{error, Reason} -> {failure, Reason};
_ -> unknown
end.
3.3 选择建议 #
- 函数子句:顶层逻辑分支
- case:内部逻辑分支
四、布尔表达式 #
4.1 短路求值 #
erlang
-module(short_circuit).
-export([safe_divide/2, safe_access/2]).
safe_divide(A, B) ->
B =/= 0 andalso A / B.
safe_access(Map, Key) ->
is_map(Map) andalso maps:is_key(Key, Map) andalso maps:get(Key, Map).
4.2 andalso/orelse #
erlang
-module(andalso_orelse).
-export([validate/1]).
validate(#{name := Name, age := Age}) ->
is_binary(Name) andalso
byte_size(Name) > 0 andalso
is_integer(Age) andalso
Age >= 0 andalso
Age =< 150;
validate(_) -> false.
4.3 and/or vs andalso/orelse #
erlang
-module(and_vs_andalso).
-export([demo/0]).
demo() ->
R1 = (true and error),
R2 = (false orelse error),
io:format("R1: ~p~n", [R1]),
io:format("R2: ~p~n", [R2]),
ok.
| 操作符 | 求值方式 | 适用场景 |
|---|---|---|
and |
两边都求值 | 守卫中 |
andalso |
短路求值 | 一般代码 |
or |
两边都求值 | 守卫中 |
orelse |
短路求值 | 一般代码 |
五、条件表达式技巧 #
5.1 使用模式匹配替代if #
erlang
-module(pattern_vs_if).
-export([classify_v1/1, classify_v2/1]).
classify_v1(N) ->
if N > 0 -> positive;
N < 0 -> negative;
true -> zero
end.
classify_v1(N) when N > 0 -> positive;
classify_v1(N) when N < 0 -> negative;
classify_v1(0) -> zero.
5.2 使用辅助函数 #
erlang
-module(helper_function).
-export([process/1]).
process(Data) ->
case classify(Data) of
type_a -> handle_a(Data);
type_b -> handle_b(Data);
unknown -> handle_unknown(Data)
end.
classify({a, _}) -> type_a;
classify({b, _}) -> type_b;
classify(_) -> unknown.
handle_a({a, Value}) -> {processed_a, Value}.
handle_b({b, Value}) -> {processed_b, Value}.
handle_unknown(_) -> {error, unknown_type}.
5.3 避免深层嵌套 #
erlang
-module(avoid_nested).
-export([good/1, bad/1]).
bad(Data) ->
case Data of
{ok, Value} ->
case process(Value) of
{ok, Result} ->
case validate(Result) of
ok -> {success, Result};
{error, Reason} -> {error, Reason}
end;
{error, Reason} -> {error, Reason}
end;
{error, Reason} -> {error, Reason}
end.
good(Data) ->
with(Data, [
fun check_ok/1,
fun process/1,
fun validate/1
]).
check_ok({ok, Value}) -> {ok, Value};
check_ok({error, Reason}) -> {error, Reason}.
process({ok, Value}) -> {ok, {processed, Value}}.
validate({ok, _Result}) -> ok.
with({error, _} = Error, _) -> Error;
with({ok, Value}, [Fun | Rest]) -> with(Fun({ok, Value}), Rest);
with({ok, Value}, []) -> {ok, Value}.
六、实际应用 #
6.1 HTTP状态处理 #
erlang
-module(http_status).
-export([handle/1]).
handle(Status) ->
case Status of
200 -> ok;
201 -> created;
204 -> no_content;
400 -> {error, bad_request};
401 -> {error, unauthorized};
403 -> {error, forbidden};
404 -> {error, not_found};
500 -> {error, internal_server_error};
Code when Code >= 200, Code < 300 -> {success, Code};
Code when Code >= 400, Code < 500 -> {client_error, Code};
Code when Code >= 500 -> {server_error, Code}
end.
6.2 配置验证 #
erlang
-module(config_validate).
-export([validate/1]).
validate(Config) ->
Checks = [
fun check_host/1,
fun check_port/1,
fun check_timeout/1
],
run_checks(Config, Checks).
run_checks(_Config, []) -> ok;
run_checks(Config, [Check | Rest]) ->
case Check(Config) of
ok -> run_checks(Config, Rest);
{error, _} = Error -> Error
end.
check_host(#{host := Host}) when is_binary(Host), byte_size(Host) > 0 -> ok;
check_host(#{host := _}) -> {error, invalid_host};
check_host(_) -> {error, missing_host}.
check_port(#{port := Port}) when is_integer(Port), Port > 0, Port =< 65535 -> ok;
check_port(#{port := _}) -> {error, invalid_port};
check_port(_) -> {error, missing_port}.
check_timeout(#{timeout := Timeout}) when is_integer(Timeout), Timeout > 0 -> ok;
check_timeout(#{timeout := _}) -> {error, invalid_timeout};
check_timeout(_) -> ok.
6.3 消息路由 #
erlang
-module(message_router).
-export([route/1]).
route({chat, From, To, Message}) ->
io:format("Chat from ~p to ~p: ~p~n", [From, To, Message]),
delivered;
route({broadcast, From, Message}) ->
io:format("Broadcast from ~p: ~p~n", [From, Message]),
delivered;
route({join, User, Room}) ->
io:format("~p joined ~p~n", [User, Room]),
joined;
route({leave, User, Room}) ->
io:format("~p left ~p~n", [User, Room]),
left;
route(Unknown) ->
io:format("Unknown message: ~p~n", [Unknown]),
ignored.
七、最佳实践 #
7.1 保持分支简单 #
erlang
-module(simple_branch).
-export([good/1, bad/1]).
good({ok, Value}) -> {success, Value};
good({error, Reason}) -> {failure, Reason}.
bad(Result) ->
case Result of
{ok, {nested, {deep, {value, Value}}}} ->
{success, {complex, Value}};
{error, {nested, {deep, {reason, Reason}}}} ->
{failure, {complex, Reason}}
end.
7.2 使用有意义的模式 #
erlang
-module(meaningful_pattern).
-export([handle/1]).
handle({user_request, UserId, Action}) ->
process_user_action(UserId, Action);
handle({system_event, EventType, Data}) ->
process_system_event(EventType, Data);
handle({admin_command, Command}) ->
process_admin_command(Command).
process_user_action(_, _) -> ok.
process_system_event(_, _) -> ok.
process_admin_command(_) -> ok.
7.3 处理所有情况 #
erlang
-module(handle_all).
-export([process/1]).
process({ok, Value}) -> {success, Value};
process({error, Reason}) -> {failure, Reason};
process(Other) -> {unexpected, Other}.
八、总结 #
本章学习了:
- if表达式
- case表达式
- 布尔表达式
- 条件表达式技巧
- 实际应用案例
- 最佳实践
准备好学习递归与循环了吗?让我们进入下一章。
最后更新:2026-03-27