Erlang 的 匹配模式、关卡、表达式

模式匹配

模式 = 单元结果
{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
[HT] = [1, 2, 3, 4, 5]
[HT] = “cat”
[A, B, CT] = [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
    
  • 执行过程
    1. 首先 Expression 被执行,其值为 Value。
    2. 随后 Value 轮流与 Pattern1(可选关卡)、Pattern2等模式进行匹配,直到匹配成功
    3. 发现匹配,相应的表达式序列就会执行,而表达式的结果就是 case 表达式的值
    4. 如果所有模式都不匹配,就会发生异常错误( 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
    
  • 执行过程
    1. 如果 Guard1 的值为 true,那么执行 Expr_seq1,if 的值 为 Expr_seq1 的值
    2. 如果 Guard1 的值为 false,那么执行 Guard2。以此类推直到某个关卡成功为止
    3. if 表达式必须至少有一个关卡的执行结果为 true。否则就会发生异常错误
  • 示例
    if
        A > 0 ->
            do_this()
        a -> true % 我自己随便写的
    end
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值