Erlang入門教程 - 12. If 和Case

函數find_max_and_min(見Erlang入門教程 - 11. List進階)可以找出氣溫極值。一個新的結構,if, 在這裡引入,也可以完成這項工作。If的工作機制如下:

ifn Condition 1 ->n Action 1;n Condition 2 ->n Action 2;n Condition 3 ->n Action 3;n Condition 4 ->n Action 4nendn

注意在end之前沒有」;」Conditions類似於guards,即測試成功或者失敗。Erlang從上面開始測試直到找到一個條件(Condition)測試成功。然後它求值(執行)條件後跟著的Action並且忽略其它的條件和行為(Actions)。如果沒有條件匹配,就會引發運行時異常。通常有一個條件總是能通過測試即true原子。它通常位於if的最後一個條件,對應的action執行其他條件都測試失敗後該做的事情。

下面短小的程序顯示了if是如何工作的:

-module(tut9).n-export([test_if/2]).nntest_if(A, B) ->n if n A == 5 ->n io:format("A == 5~n", []),n a_equals_5;n B == 6 ->n io:format("B == 6~n", []),n b_equals_6;n A == 2, B == 3 -> %That is A equals 2 and B equals 3n io:format("A == 2, B == 3~n", []),n a_equals_2_b_equals_3;n A == 1 ; B == 7 -> %That is A equals 1 or B equals 7n io:format("A == 1 ; B == 7~n", []),n a_equals_1_or_b_equals_7n end.n

測試這個程序:

60> c(tut9).n{ok,tut9}n61> tut9:test_if(5,33).nA == 5na_equals_5n62> tut9:test_if(33,6).nB == 6nb_equals_6n63> tut9:test_if(2, 3).nA == 2, B == 3na_equals_2_b_equals_3n64> tut9:test_if(1, 33).nA == 1 ; B == 7na_equals_1_or_b_equals_7n65> tut9:test_if(33, 7).nA == 1 ; B == 7na_equals_1_or_b_equals_7n66> tut9:test_if(33, 33).n** exception error: no true branch found when evaluating an if expressionn in function tut9:test_if/2 (tut9.erl, line 5)n

tut9:test_if(33,33)沒有使任何條件測試成功。這引發了一個運行時錯誤,在這裡shell漂亮的格式化了錯誤消息。

case是Erlang的另一個結構。回憶一下convert_length函數是這樣寫的:

convert_length({centimeter, X}) ->n {inch, X / 2.54};nconvert_length({inch, Y}) ->n {centimeter, Y * 2.54}.n

同樣的程序也可以這樣寫:

-module(tut10).n-export([convert_length/1]).nnconvert_length(Length) ->n case Length ofn {centimeter, X} ->n {inch, X / 2.54};n {inch, Y} ->n {centimeter, Y * 2.54}n end.n

67> c(tut10).n{ok,tut10}n68> tut10:convert_length({inch, 6}).n{centimeter,15.24}n69> tut10:convert_length({centimeter, 2.5}).n{inch,0.984251968503937}n

case和if都有返回值,也就是說,在上面的case例子中返回{inch,X/2.54}或者{centimeter,Y*2.54}。case的行為也可以使用guards修改。下面的例子解釋了這一點。給它指定的年月它告訴我們該月有多少天。

-module(tut11).n-export([month_length/2]).nnmonth_length(Year, Month) ->n %% All years divisible by 400 are leapn %% Years divisible by 100 are not leap (except the 400 rule above)n %% Years divisible by 4 are leap (except the 100 rule above)n Leap = ifn trunc(Year / 400) * 400 == Year ->n leap;n trunc(Year / 100) * 100 == Year ->n not_leap;n trunc(Year / 4) * 4 == Year ->n leap;n true ->n not_leapn end, n case Month ofn sep -> 30;n apr -> 30;n jun -> 30;n nov -> 30;n feb when Leap == leap -> 29;n feb -> 28;n jan -> 31;n mar -> 31;n may -> 31;n jul -> 31;n aug -> 31;n oct -> 31;n dec -> 31n end.n70> c(tut11).n{ok,tut11}n71> tut11:month_length(2004, feb).n29n72> tut11:month_length(2003, feb).n28n73> tut11:month_length(1947, aug).n31n

推薦閱讀:

仙境里的Haskell(之七)—— IO Monad
Algebra of Programming - initial algebra

TAG:Erlang编程语言 | 函数式编程 | 编程语言 |