Erlang 匹配、Guards 與變量的作用域

2018-11-28 22:43 更新

Erlang匹配、Guards 與變量的作用域

在某些場(chǎng)景下,我們可能需要找到最高溫度或最低溫度。所以查找溫度值列表中最大值或最小值是非常有用的。在擴(kuò)展程序?qū)崿F(xiàn)該功能之前,讓我們先看一下尋找列表中的最大值的方法:

-module(tut6).
-export([list_max/1]).

list_max([Head|Rest]) ->
   list_max(Rest, Head).

list_max([], Res) ->
    Res;
list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->
    list_max(Rest, Head);
list_max([Head|Rest], Result_so_far)  ->
    list_max(Rest, Result_so_far).
37> c(tut6).
{ok,tut6}
38> tut6:list_max([1,2,3,4,5,7,4,3,2,1]).
7

首先注意這兩個(gè)函數(shù)的名稱(chēng)是完全相同的。但是,由于它們接受不同數(shù)目的參數(shù),所以在 Erlang 中它們被當(dāng)作兩個(gè)完全不相同的函數(shù)。在你需要使用它們的時(shí)候,你使用名稱(chēng)/參數(shù)數(shù)量的方式就可以了,這里名稱(chēng)就是函數(shù)的名稱(chēng),參數(shù)數(shù)量是指函數(shù)的參數(shù)的個(gè)數(shù)。這個(gè)例子中為 list_max/1list_max/2

在本例中,遍歷列表的中元素過(guò)程中 “攜帶” 了一個(gè)值(最大值),即 Result_so_far。 list_max/1 函數(shù)把列表中的第一個(gè)元素當(dāng)作最大值元素,然后使用剩余的元素作參數(shù)調(diào)用函數(shù) list_max/2。在上面的例子中為 list_max([2,3,4,5,6,7,4,3,2,1],1)。如果你使用空列表或者非列表類(lèi)型的數(shù)據(jù)作為實(shí)參調(diào)用 list_max/1,則會(huì)產(chǎn)生一個(gè)錯(cuò)誤。注意,Erlang 的哲學(xué)是不要在錯(cuò)誤產(chǎn)生的地方處理錯(cuò)誤,而應(yīng)該在專(zhuān)門(mén)處理錯(cuò)誤的地方來(lái)處理錯(cuò)誤。稍后會(huì)詳細(xì)說(shuō)明。

list_max/2 中,當(dāng) Head > Result_so_far 時(shí),則使用 Head 代替 Result_so_far 并繼續(xù)調(diào)用函數(shù)。 when 用在函數(shù)的 -> 前時(shí)是一個(gè)特別的的單詞,它表示只有測(cè)試條件為真時(shí)才會(huì)用到函數(shù)的這一部分。這種類(lèi)型的測(cè)試被稱(chēng)這為 guard。如果 guard 為假 (即 guard 測(cè)試失敗),則跳過(guò)此部分而嘗試使用函數(shù)的后面一部分。這個(gè)例子中,如果 Head 不大于 Result_so_far 則必小于或等于。所以在函數(shù)的下一部分中不需要 guard 測(cè)試。

可以用在 guard 中的操作符還包括:

  • <小于
  • > 大于
  • == 等于
  • >= 大于或等于
  • =< 小于或等于
  • /= 不等于

(詳見(jiàn) Guard Sequences

要將上面找最大值的程序修改為查找最小值元素非常容易,只需要將 > 變成 < 就可以了。(但是,最好將函數(shù)名同時(shí)也修改為 list_min

前面我們提到過(guò),每個(gè)變量在其作用域內(nèi)只能被賦值一次。從上面的例子中也可以看到,Result_so_far 卻被賦值多次。這是因?yàn)?,每次調(diào)用一次 list_max/2 函數(shù)都會(huì)創(chuàng)建一個(gè)新的作用域。在每個(gè)不同的作用域中,Result_so_far 都被當(dāng)作完全不同的變量。

另外,我們可以使用匹配操作符 = 創(chuàng)建一個(gè)變量并給這個(gè)變量賦值。因此,M = 5 創(chuàng)建了一個(gè)變量 M,并給其賦值為 5。如果在相同的作用域中,你再寫(xiě) M = 6, 則會(huì)導(dǎo)致錯(cuò)誤??梢栽?shell 中嘗試一下:

39> M = 5.
5
40> M = 6.
** exception error: no match of right hand side value 6
41> M = M + 1.
** exception error: no match of right hand side value 6
42> N = M + 1.
6

除了創(chuàng)建新變量外,匹配操作符另一個(gè)用處就是將 Erlang 項(xiàng)分開(kāi)。

43> {X, Y} = {paris, {f, 28}}.
{paris,{f,28}}
44> X.
paris
45> Y.
{f,28}

如上,X 值為 paris,而 Y 的值為 {f,28}。

如果同樣用 X 和 Y 再使用一次,則會(huì)產(chǎn)生一個(gè)錯(cuò)誤:

46> {X, Y} = {london, {f, 36}}.
** exception error: no match of right hand side value {london,{f,36}}

變量用來(lái)提高程序的可讀性。例如,在 list_max/2 函數(shù)中,你可以這樣寫(xiě):

list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->
    New_result_far = Head,
    list_max(Rest, New_result_far);

這樣寫(xiě)可以讓程序更加清晰。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)