iT邦幫忙

DAY 12
1

蠻可愛的 Erlang 與 Elixir系列 第 12

Higher-order functions

前面曾經介紹過,用函數當函數參數.
今天介紹進階的應用,這種方式稱為
Higher-order functions.

來看一下範例程式:

-module(hhfuns).
-compile(export_all).

increment([]) -> [];
increment([H | T]) ->
  [H + 1 | increment(T)].

decrement([]) -> [];
decrement([H | T]) ->
  [H - 1 | decrement(T)].

map(_, []) -> [];
map(F, [H | T]) ->
  [F(H) | map(F, T)].

incr(X) -> X + 1.
decr(X) -> X - 1.

編譯及執行:

1> c(hhfuns).
{ok,hhfuns}
2> L = [2,7,5,3].
[2,7,5,3]
3> hhfuns:increment(L).
[3,8,6,4]
4> hhfuns:decrement(L).
[1,6,4,2]
5> hhfuns:map(fun hhfuns:incr/1, L).
[3,8,6,4]
6> hhfuns:map(fun hhfuns:decr/1, L).
[1,6,4,2]

解說:
increment()的功能是將傳入的List,使用遞迴的方式,將內容加1.
decrement()則是減1.
但是我們這樣為了某樣功能,就要開發一個遞迴方式的函數.
接著看map/2 <== 這是erlang 習慣的表示法,代表傳入兩個參數.
map/2透過傳入的函數F與List,使用遞迴方式,從頭部逐一取出List內容,
傳入F運算後,放到新的List頭部.最終傳出新的List.
後面另外定義了incr/1, decr/1 分別做加減.
這樣子透過map/2與incr/1與decr/1的組合方式,會比寫increment/1, decrement/1
方便許多.
若我們要作偶數的判斷,只要新增一個偶數判斷函數即可,無須再自己寫遞迴型態的
偶數判斷函數了.

將偶數判斷函數增加進去:

-module(hhfuns).
-compile(export_all).

increment([]) -> [];
increment([H | T]) ->
  [H + 1 | increment(T)].

decrement([]) -> [];
decrement([H | T]) ->
  [H - 1 | decrement(T)].

map(_, []) -> [];
map(F, [H | T]) ->
  [F(H) | map(F, T)].

incr(X) -> X + 1.
decr(X) -> X - 1.

even(X) -> (X rem 2) =:= 0.

再編譯及執行:

7> c(hhfuns).
{ok,hhfuns}
8> hhfuns:map(fun hhfuns:even/1, L).
[true,false,false,false]

可以看到even/1搭配map/2,就可以輕易的對傳入的List,
做判斷.
注意到 -complile(export_all).
這代表模組裡的每一個函數都會傳出,可被外部呼叫.
取代了 -export([map/2, incr/1]) 這樣的方式.

我們也可以使用List Comprehension的方式.

9> [hhfuns:incr(X) || X <- L].             
[3,8,6,4]
10> [hhfuns:decr(X) || X <- L].
[1,6,4,2]
11> [hhfuns:even(X) || X <- L].
[true,false,false,false]

erlang裡面有提供lists:map/2 供我們使用,
需要使用時,無須再自行開發,在此的map/2是用來說明.

看到這裡,也許會有一個疑問,既然List Comprehension 好像
也能達到同樣功效,那為何還需要再用Higher-order functions呢?
因為Higher-order functions後面是有加s的,代表多種,常見的有
map,filter;我們還可視需要開發更強大的功能來應用.
List Comprehension名稱已經說明了就是針對List,
最後得到的還是List,List雖是主角,
我們有時候需要得到tuple或是其他型態.
程式語言是很靈活,我們可以視需要來搭配使用.


上一篇
尾遞迴
下一篇
Concurrent Programming
系列文
蠻可愛的 Erlang 與 Elixir30

尚未有邦友留言

立即登入留言