模式匹配
模式 = 单元 | 结果 |
---|---|
{X, abc} = {123, abc} | 成功:X = 123 |
{X, Y, Z} = {222, def, “cat”} | 成功:X = 222, Y = def, Z = “cat” |
{X, Y} = {333, ghi, “cat”} | 失败:元组的结构不同 |
X = true | 成功:X = true |
{X, Y, X} = {{abc, 12}, 42, {abc, 12}} | 成功:X = {abc, 12} Y = 42 |
{X, Y, X} = {{abc, 12}, 42, true} | 失败:X不能既是 {abc, 12} 又是 true |
[H | T] = [1, 2, 3, 4, 5] |
[H | T] = “cat” |
[A, B, C | T] = [a, b, c, d, e, f] |
关卡(guard)
是一种结构,可以用它来增加模式匹配的威力。
可以对某个模式里的变量执行简单的测试和比较。
- 关卡由一系列关卡表达式组成,用逗号(,)分割
GuardExpr1,GuardExpr2, …,GuardExprN,所有关卡表达式都为 true 时才为 true - 关卡表达式是所有Erlang表达式的一个子集。关卡不能调用用户定义的函数
- 原子 true;
- 其它常量(各种数据结构和已绑定变量),在关卡表达式里都为 false;
- 调用后面表1里的关卡判断函数和表2里的内置函数
- 数据结构比较 参考表6
- 算术表达式 参考表3
- 布尔表达式 参考8.7
- 短路布尔表达式 参考8.23
- 关卡序列(guard sequence)是指单一或一系列的关卡,用分号(;)分割。
G1;G2; …; Gn,只要其中有一个关卡的值为 true,它的值就为 true - 示例
% 当句1里 X > Y 时,才会执行句2 max(X, Y) when X > Y -> X; % 当 X 大于 Y时,返回 X max(X, Y) -> Y. % 如果句1匹配,则返回 Y % 当X是一个整数、X 大于 Y 并且 Y 小于6时 f(X,Y) when is_integer(X), X > Y, Y < 6 -> ... % T是一个包含六个元素的元组,并且T中第三个元素的绝对值大于5 is_tuple(T), tuple_size(T) =:= 6, abs(element(3, T)) > 5 % 元组X的第4个元素与列表L的列表头相同 element(4, X) =:= hd(L) % X是一个 cat 或者 dog X =:= dog; X =:= cat % X 是整数,并且 X 大于 Y 或者 Y 的绝对值小于 23 is_integer(X), X > Y; abs(Y) < 23 % A 大于等于 -1 并且 A 加 1 小于 B A >= -1.0 andalso A+1 > B % 如果 L 是个原子,那么判断 L 是个列表 并且 L 的长度大于 2 is_atom(L) orelse ( is_list(L) andalso length(L) > 2)
短路布尔表达式
andalso
orelse
- andalso 与 and 的区别
% 当 X 为 0 时,f(X) 里的关卡会失败,但 g(X) 里的关卡会成功 f(X) when (X == 0) or (1/X > 2) -> ... g(X) when (X == 0) orelse (1/X > 2) -> ...
case 表达式
- 语法
case Expression of Pattern1 [when Guard1] -> Expr_seq1; Pattern2 [when Guard2] -> Expr_seq1; ... end
- 执行过程
- 首先 Expression 被执行,其值为 Value。
- 随后 Value 轮流与 Pattern1(可选关卡)、Pattern2等模式进行匹配,直到匹配成功
- 发现匹配,相应的表达式序列就会执行,而表达式的结果就是 case 表达式的值
- 如果所有模式都不匹配,就会发生异常错误( exception )
- 示例
filter( P, [H | T] ) -> case P(H) of true -> [ H | filter(P, T) ]; false -> filter(P, T) end filter( P, [] ) -> []. % case 不是必须的。下面只用模式匹配来定义 filter filter( P, [H | T] ) -> filter( P(H), H, P, T ); filter( P, [] ) -> []. filter1(true, H, P, T) -> [H | filter(P, T)]; filter1(false, H, P, T) -> filter(P, T) % 这个定义比较丑。必须建立额外的函数 filter1,并向 filter/2 传递所有参数
if 表达式
- 语法
if Guard1 -> Expr_seq1; Guard2 -> Expr_seq1; ... end
- 执行过程
- 如果 Guard1 的值为 true,那么执行 Expr_seq1,if 的值 为 Expr_seq1 的值
- 如果 Guard1 的值为 false,那么执行 Guard2。以此类推直到某个关卡成功为止
- if 表达式必须至少有一个关卡的执行结果为 true。否则就会发生异常错误
- 示例
if A > 0 -> do_this() a -> true % 我自己随便写的 end