首页 > Erlang快速入门 > 3.11 Erlang快速入门之if和case
2013
11-01

3.11 Erlang快速入门之if和case

If 和 Case 语句
函数find_max_and_min将为我们找到最高和最低气温。我们在这里引入了一个新的关键字if,它的工作情况如下:
if
Condition 1 ->
Action 1;
Condition 2 ->
Action 2;
Condition 3 ->
Action 3;
Condition 4 ->
Action 4
end

注意,在end前面的最后一个条件是没有“;”的!这里的判定条件和界定(Guard)是一样的,测试条件的真或假。Erlang从最高处开始执行,直到它找到一个为真的条件,并执行其内部的代码,并且很重要的是它将忽略其他剩下的条件,不论其他剩下的条件中是否还有为真的情况。一个条件当是常量的时候意味着永远为真,true和常量(atoms)常常用来作为if的最后一个条件。作为当其他所有条件都为假时的执行出口。
下面是一个简短的程序,用来表现if工作的情况:

-module(tut9).
-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 ->                      %i.e. A equals 2 and B equals 3
            io:format("A == 2, B == 3~n", []),
            a_equals_2_b_equals_3;
        A == 1 ; B == 7 ->                     %i.e. A equals 1 or B equals 7
            io:format("A == 1 ; B == 7~n", []),
            a_equals_1_or_b_equals_7
    end.    

下面是对程序的测试:

64> c(tut9).
{ok,tut9}
65> tut9:test_if(5,33).
A = 5
a_equals_5
66> tut9:test_if(33,6).
B = 6
b_equals_6
67> tut9:test_if(2, 3).
A == 2, B == 3
a_equals_2_b_equals_3
68> tut9:test_if(1, 33).
A == 1 ; B == 7
a_equals_1_or_b_equals_7
69> tut9:test_if(33, 7).
A == 1 ; B == 7
a_equals_1_or_b_equals_7
70> tut9:test_if(33, 33).
=ERROR REPORT==== 11-Jun-2003::14:03:43 ===
Error in process <0.85.0> with exit value: 
{if_clause,[{tut9,test_if,2},{erl_eval,exprs,4},{shell,eval_loop,2}]}
** exited: {if_clause,[{tut9,test_if,2},
                          {erl_eval,exprs,4},
                          {shell,eval_loop,2}]} **

注意到执行tut9:test_if(33,33)时由于没有任何条件可以满足时出现了错误if_clause。case是另外一种Erlang中的判断结构。回忆我们以前写的convert_length函数:
convert_length({centimeter, X}) ->
{inch, X / 2.54};
convert_length({inch, Y}) ->
{centimeter, Y * 2.54}.

我们可以改写为:

-module(tut10).
-export([convert_length/1]).

convert_length(Length) ->
    case Length of
        {centimeter, X} ->
            {inch, X / 2.54};
        {inch, Y} ->
            {centimeter, Y * 2.54}
    end.  
71> c(tut10).
{ok,tut10}
72> tut10:convert_length({inch, 6}).
{centimeter,15.2400}
73> tut10:convert_length({centimeter, 2.5}).
{inch,0.98425}    

注意case和if都有返回值,在上面的例子中case返回{inch,X/2.54}或者{centimeter,Y*2.54}。case的行为可以被界定(Guard)修改。一个例子可能能够更加清楚的说明这个问题。下面的例子告诉我们给定了年份时某个月份的天数。我们需要知道年份是理所应当的,毕竟有闰年的情况需要处理嘛:

-module(tut11).
-export([month_length/2]).
month_length(Year, Month) ->
    %% All years divisible by 400 are leap
    %% Years divisible by 100 are not leap (except the 400 rule above)
    %% Years divisible by 4 are leap (except the 100 rule above)
    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.  
  
74> c(tut11).
{ok,tut11}
75> tut11:month_length(2004, feb).
29
76> tut11:month_length(2003, feb).
28
77> tut11:month_length(1947, aug).
31 

留下一个回复

你的email不会被公开。