• 原语
    • Case
    • If
    • Case 和 if 使用示例

    原语

    Erlang提供了元语caseif,这样在子句中无需借助其他函数便可以直接进行条件求值。

    Case

    case表达式允许在子句主体内部于多个选项中进行选择,语法如下:

    1. case Expr of
    2. Pattern1 [when Guard1] -> Seq1;
    3. Pattern2 [when Guard2] -> Seq2;
    4. ...
    5. PatternN [when GuardN] -> SeqN
    6. end

    首先,对Expr求值,然后,Expr的值将依次与模式Pattern1Pattern2……PatternN进行匹配,直到匹配成功。如果找到一个匹配并且(可选的)的保护式成立,则对应的调用序列将被求值。注意case保护式与函数保护式形式相同。case原语的值就是被选中的序列的值。

    至少得有一个模式必须得以匹配——否则就会产生一个运行时错误并引发第??章中的错误处理机制。

    举个例子,比方说我们我有个函数allocate(Resource)用于分配某种资源Resource。假设这个函数只返回{yes,Address}no。这样,这个函数便可以放在一个case结构里:

    1. ...
    2. case allocate(Resource) of
    3. {yes,Address} when Address > 0, Address =< Max ->
    4. Sequence 1 ... ;
    5. no ->
    6. Sequence 2 ...
    7. end
    8. ...

    Sequence1…中,变量Address已经被绑定在了allocate/1的返回结果上。

    为了避免匹配错误的发生,我们常常追加一个必会匹配的模式[6]作为case原语的最后一个分支:

    1. case Fn of
    2. ...
    3. _ ->
    4. true
    5. end

    If

    if表达式的语法如下:

    1. if
    2. Guard1 ->
    3. Sequence1 ;
    4. Guard2 ->
    5. Sequence2 ;
    6. ...
    7. end

    在这种情况下,保护式Guard1,…将被依次求值。如果一个保护式成立则对与之关联的序列求值。该序列的求值结果便是if结构的结果。if保护式与函数保护式形式相同。与case相同,一个保护式都不成立的话将引发一个错误。如果需要,可以增加保护式断言true作为垃圾箱:

    1. if
    2. ...
    3. true ->
    4. true
    5. end

    Case 和 if 使用示例

    使用caseif我们可以以多种方式来编写factorial

    最简单的:

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

    使用函数保护式:

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

    使用if

    1. factorial(N) ->
    2. if
    3. N == 0 -> 1;
    4. N > 0 -> N * factorial(N - 1)
    5. end.

    使用case

    1. factorial(N) ->
    2. case N of
    3. 0 -> 1;
    4. N when N > 0 ->
    5. N * factorial(N - 1)
    6. end.

    使用变量保持临时结果:

    1. factorial(0) ->
    2. 1;
    3. factorial(N) when N > 0 ->
    4. N1 = N - 1,
    5. F1 = factorial(N1),
    6. N * F1.

    以上所有定义都是正确且等价的[7]——如何进行选择完全是个美学问题[8]。