Erlang入門教程 - 10. 模式匹配,Guard,變數作用域
像這樣如果能找出列表中最高/最低氣溫是很有用的。在擴展程序以尋找氣溫極值之前,讓我們看看在函數中尋找列表最大值:
-module(tut6).n-export([list_max/1]).nnlist_max([Head|Rest]) ->n list_max(Rest, Head).nnlist_max([], Res) ->n Res;nlist_max([Head|Rest], Result_so_far) when Head > Result_so_far ->n list_max(Rest, Head);nlist_max([Head|Rest], Result_so_far) ->n list_max(Rest, Result_so_far).n
37> c(tut6).n{ok,tut6}n38> tut6:list_max([1,2,3,4,5,7,4,3,2,1]).n7n
首先注意有兩個函數名字一樣,list_max(指list_max([Head|Rest])和list_max([], Res))。然而,它們接受不同數目的參數。在Erlang中它們被視作完全不同的函數。
當你需要區分這些函數的時候,你直接寫 Name/Arity 即可,Name是函數名,Arity是函數參數個數,在這是list_max/1,list_max/2。在這個例子中你遍歷一個列表然後「帶走」一個值,即Result_so_far。list_max/1簡單的假定列表的最大值是表頭元素然後把表頭元素和列表剩餘部分傳遞給list_max/2進行調用。按上面代碼給出的參數將會調用list_max([2,3,4,5,7,4,3,2,1],1)。如果你嘗試給list_max/1一個空列表或者給它一個不是列表的值,將引發一個錯誤。Erlang的哲學是不在函數中處理這類錯誤,而是在其他地方處理。關於這點後面會討論。
在list_max/2, 當Head > Result_so_far時使用Head代替Result_so_far。在->後使用when表示你只在when後面的測試為true時才使用這個函數(clause)。這類測試叫做guard。如果guard為false(即guard失敗),就轉而嘗試下一個函數(clause)。在這裡,如果Head不大於Result_so_far,那它一定小於或等於。這意味著下面函數(clause)不需要guard。
在guards中有這麼一些有用的運算符:
- < 小於
- > 大於
- == 等於
- >= 大於等於
- =< 小於等於
- /= 不等於
要修改上面的程序讓它找出列表中的最小值,你只需要把>改成<。(但那樣做最好也把函數名改成list_min)。
之前提到過一個變數在它的作用域內只能綁定一次值。但如你所見Result_so_far綁定了很多次值。這沒問題,因為每次你調用list_max/2都會創建一個新的作用域,然後Result_so_far就在那個新作用域中進行綁定。
另一個創建變數並綁定值的方法是使用匹配運算符=。當你寫下M = 5,一個名為M的變數創建了並綁定值5。如果,在相同的作用域,你寫下M =6,就會返回錯誤。在shell中試試:
39> M = 5.n5n40> M = 6.n** exception error: no match of right hand side value 6n41> M = M + 1.n** exception error: no match of right hand side value 6n42> N = M + 1.n6n
匹配運算符在分離Erlang 一個項並創建新項時是非常有用的。
43> {X, Y} = {paris, {f, 28}}.n{paris,{f,28}}n44> X.nparisn45> Y.n{f,28}n
在這裡X綁定為paris,Y綁定為{f,28}。
如果你嘗試再使用其它城市,就會返回一個錯誤。
46> {X, Y} = {london, {f, 36}}.n** exception error: no match of right hand side value {london,{f,36}}n
變數也可用於改善程序可讀性。舉個例子,在上面的list_max/2函數中,你可以這麼寫:
list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->n New_result_far = Head,n list_max(Rest, New_result_far);n
這樣可能更清晰一些。
推薦閱讀:
※C語言為何不改進數組?
※Lisp 和 Haskell 各有什麼優缺點?學哪個好?
※C# 兩種遍歷列表的方式,哪種更高效?
※為什麼數據分析需要會編程語言?
※為什麼很多語言中,要用三個引號或其他符號來表示多行字元串字面量?
TAG:Erlang编程语言 | 函数式编程 | 编程语言 |