条件判断
if
前面的 find_max_and_min 函数里已经用到了 if
现在介绍一个新的结构 if 。If 的语法格式如下:
if Condition 1 -> Action 1; Condition 2 -> Action 2; Condition 3 -> Action 3; Condition 4 -> Action 4 end
条件 的工作方式与 guard 一样,即 测试 并返回 成功 或者 失败 :
- Erlang 从第一个条件开始测试一直到找到一个测试为真的分支,随后,执行该条件后的动作,且忽略其它在 end 前的条件与动作
- 如果所有条件都测试失败,则会产生运行时错误
- 一个测试恒为真的条件就是 true :它常用作 if 的最后一个条件,即当所有条件都测试失败时,则执行 true 后面的动作
注意:在 end 之前没有 “;”
下面这个例子说明了 if 的工作方式:
-module(conds). -export([test_if/2]). test_if(A, B) -> if A == 5 -> io:format("A == 5~n", []), a_equals_5; B == 6 -> io:format("B == 6~n", []), b_equals_6; A == 2, B == 3 -> %That is A equals 2 and B equals 3 io:format("A == 2, B == 3~n", []), a_equals_2_b_equals_3; A == 1 ; B == 7 -> %That is A equals 1 or B equals 7 io:format("A == 1 ; B == 7~n", []), a_equals_1_or_b_equals_7 end.
测试该程序:
8> conds:test_if(5,33). A == 5 a_equals_5 9> conds:test_if(33,6). B == 6 b_equals_6 10> conds:test_if(2,3). A == 2, B == 3 a_equals_2_b_equals_3 11> conds:test_if(1,33). A == 1 ; B == 7 a_equals_1_or_b_equals_7 12> conds:test_if(33,33). ** exception error: no true branch found when evaluating an if expression in function conds:test_if/2 (conds.erl, line 5)
注意:conds:test_if(33,33) 使得所有测试条件都失败,这将导致产生一个 if_clause 运行时错误
case
Erlang 中还有一种 case 结构。回想一下前面的 convert_length 函数:
convert_length({centimeter, X}) -> {inch, X / 2.54}; convert_length({inch, Y}) -> {centimeter, Y * 2.54}.
该函数也可以用 case 实现,如下所示:
-module(conds). -export([convert_length/1]). convert_length(Length) -> case Length of {centimeter, X} -> {inch, X / 2.54}; {inch, Y} -> {centimeter, Y * 2.54} end.
无论是 case 还是 if 都有返回值
这也就是说,上面的例子中,case 语句要么返回 {inch,X/2.54} 要么返回 {centimeter,Y*2.54}。
case 语句也可以用 guard 子句 来实现。下面的例子可以帮助你分清二者。这个例子中,输入年份得到指定某月的天数。年份必须是已知的,因为闰年的二月有 29 天,所以必须根据年份才能判断二月的天数:
-module(conds). -export([month_length/2]). month_length(Year, Month) -> %% 被 400 整除的为闰年。 %% 被 100 整除但不能被 400 整除的不是闰年。 %% 被 4 整除但不能被 100 整除的为闰年。 Leap = if trunc(Year / 400) * 400 == Year -> leap; trunc(Year / 100) * 100 == Year -> not_leap; trunc(Year / 4) * 4 == Year -> leap; true -> not_leap end, case Month of sep -> 30; apr -> 30; jun -> 30; nov -> 30; feb when Leap == leap -> 29; feb -> 28; jan -> 31; mar -> 31; may -> 31; jul -> 31; aug -> 31; oct -> 31; dec -> 31 end.
测试:
16> conds:month_length(2004,feb). 29 17> conds:month_length(2003,feb). 28 18> conds:month_length(1947,jan). 31 19> conds:month_length(1947,jan1). ** exception error: no case clause matching jan1 in function conds:month_length/2 (conds.erl, line 42)
从例子中可以看出:when是不一定需要返回值的!