Erlang 高階函數(shù) (Fun)

2022-07-07 15:40 更新

Erlang 高階函數(shù) (Fun)

Erlang 作為函數(shù)式編程語(yǔ)言自然擁有高階函數(shù)。在 shell 中,我們可以這樣使用:

86> Xf = fun(X) -> X * 2 end.
 #Fun<erl_eval.5.123085357>
87> Xf(5).
10

這里定義了一個(gè)數(shù)值翻倍的函數(shù),并將這個(gè)函數(shù)賦給了一個(gè)變量。所以,Xf(5) 返回值為 10。Erlang 有兩個(gè)非常有用的操作列表的函數(shù) foreach 與 map, 定義如下:

foreach(Fun, [First|Rest]) ->
    Fun(First),
    foreach(Fun, Rest);
foreach(Fun, []) ->
    ok.

map(Fun, [First|Rest]) -> 
    [Fun(First)|map(Fun,Rest)];
map(Fun, []) -> 
    [].

這兩個(gè)函數(shù)是由標(biāo)準(zhǔn)模塊 lists 提供的。foreach 將一個(gè)函數(shù)作用于列表中的每一個(gè)元素。 map 通過將一個(gè)函數(shù)作用于列表中的每個(gè)元素生成一個(gè)新的列表。下面,在 shell 中使用 map 的 Add_3 函數(shù)生成一個(gè)新的列表:

88> Add_3 = fun(X) -> X + 3 end.
 #Fun<erl_eval.5.123085357>
89> lists:map(Add_3, [1,2,3]).
[4,5,6]

讓我們?cè)俅屋敵鲆唤M城市的溫度值:

90> Print_City = fun({City, {X, Temp}}) -> io:format("~-15w ~w ~w~n",
[City, X, Temp]) end.
 #Fun<erl_eval.5.123085357>
91> lists:foreach(Print_City, [{moscow, {c, -10}}, {cape_town, {f, 70}},
{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
moscow          c -10
cape_town       f 70
stockholm       c -4
paris           f 28
london          f 36
ok

下面,讓我們定義一個(gè)函數(shù),這個(gè)函數(shù)用于遍歷城市溫度列表并將每個(gè)溫度值都轉(zhuǎn)換為攝氏溫度表示。如下所示:

-module(tut13).

-export([convert_list_to_c/1]).

convert_to_c({Name, {f, Temp}}) ->
    {Name, {c, trunc((Temp - 32) * 5 / 9)}};
convert_to_c({Name, {c, Temp}}) ->
    {Name, {c, Temp}}.

convert_list_to_c(List) ->
    lists:map(fun convert_to_c/1, List).
92> tut13:convert_list_to_c([{moscow, {c, -10}}, {cape_town, {f, 70}},
{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
[{moscow,{c,-10}},
 {cape_town,{c,21}},
 {stockholm,{c,-4}},
 {paris,{c,-2}},
 {london,{c,2}}]

convert_to_c 函數(shù)和之前的一樣,但是它現(xiàn)在被用作高階函數(shù):

lists:map(fun convert_to_c/1, List)

當(dāng)一個(gè)在別處定義的函數(shù)被用作高階函數(shù)時(shí),我們可以通過 Function/Arity 的方式來(lái)引用它(注意,F(xiàn)unction 為函數(shù)名,Arity 為函數(shù)的參數(shù)個(gè)數(shù))。所以在調(diào)用 map 函數(shù)時(shí),才會(huì)是 lists:map(fun convert_to_c/1, List) 這樣的形式。如上所示,convert_list_to_c 變得更加的簡(jiǎn)潔易懂。

lists 標(biāo)準(zhǔn)庫(kù)中還包括排序函數(shù) sort(Fun,List),其中 Fun 接受兩個(gè)輸入?yún)?shù),如果第一個(gè)元素比第二個(gè)元素小則函數(shù)返回真,否則返回假。把排序添加到 convert_list_to_c 中:

-module(tut13).

-export([convert_list_to_c/1]).

convert_to_c({Name, {f, Temp}}) ->
    {Name, {c, trunc((Temp - 32) * 5 / 9)}};
convert_to_c({Name, {c, Temp}}) ->
    {Name, {c, Temp}}.

convert_list_to_c(List) ->
    New_list = lists:map(fun convert_to_c/1, List),
    lists:sort(fun({_, {c, Temp1}}, {_, {c, Temp2}}) ->
                       Temp1 < Temp2 end, New_list).
93> c(tut13).
{ok,tut13}
94> tut13:convert_list_to_c([{moscow, {c, -10}}, {cape_town, {f, 70}},
{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
[{moscow,{c,-10}},
 {stockholm,{c,-4}},
 {paris,{c,-2}},
 {london,{c,2}},
 {cape_town,{c,21}}]

在 sort 中用到了下面這個(gè)函數(shù):

fun({_, {c, Temp1}}, {_, {c, Temp2}}) -> Temp1 < Temp2 end,

這兒用到了匿名變量 "_" 的概念。匿名變量常用于忽略一個(gè)獲得的變量值的場(chǎng)景下。當(dāng)然,它也可以用到其它的場(chǎng)景中,而不僅僅是在高階函數(shù)這兒。Temp1 < Temp2 說(shuō)明如果 Temp1 比 Temp2 小,則返回 true。

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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)