在 Elixir 中建立匿名函式
使用 fn
加上變數 接著用 ->
與 end
寫函數內容,如下
fn(a, b) -> a + b end
# 通常忽略括號
fn a, b -> a + b end
我們發現這裡跟第一篇使用的 case
長的有點像 ->
這邊當然也是 pattern matching 因此多個條件會變成
fn
_, 0 -> 0
a, b -> div(a, b)
end
或是之前的例子
fn
"Jack" -> "Welcome Admin Jack"
"Sam" -> "VIP"
name -> "Hi #{name}
end
adder = fn a, b -> a + b end
greet = fn
"Jack" -> "Welcome admin Jack"
name -> "Hi #{name}"
end
.()
來呼叫adder = fn a, b -> a + b end
adder.(3, 4)
#=> 7
greet = fn
"Jack" -> "Welcome admin Jack"
name -> "Hi #{name}"
end
greet.("Jack") #=> "Welcome admin Jack"
greet.("Jimmy") #=> "Hi Jimmy"
匿名函式可以做於高階函式的參數
我們這邊使用常用的 Enum.map/2
來示範
langs = ["elixir", "erlang", "ruby", "clojure", "elm"]
Enum.map(langs, fn lang -> String.upcase(lang) end)
#=> ["ELIXIR", "ERLANG", "RUBY", "CLOJURE", "ELM"]
在這邊我們在第二個變數帶入了 fn lang -> String.upcase(lang) end
這個匿名函數
想要的話也可以先放在變數,再帶入
langs = ["elixir", "erlang", "ruby", "clojure", "elm"]
upcase_fn = fn lang -> String.upcase(lang) end
Enum.map(langs, upcase_fn)
#=> ["ELIXIR", "ERLANG", "RUBY", "CLOJURE", "ELM"]
&
)(無翻譯,我翻成"捕捉運算符")
如果匿名函式單純只有呼叫令一個函數,像剛剛的範例 fn lang -> String.upcase(lang) end
我們可以使用 &
直接把 String.upcase/1
抓住變成匿名函式
upcase_fn = &String.upcase/1
Enum.map(langs, upcase_fn)
更常見的是直接在參數上抓住
Enum.map(langs, &String.upcase/1)
使用剛剛的語言列表langs = ["elixir", "erlang", "ruby", "clojure", "elm"]
假如我們今天要將每個語言重複三次
使用匿名函式可以寫成
Enum.map(langs, fn lang -> String.duplicate(lang, 3) end)
#=> ["elixirelixirelixir", "erlangerlangerlang", "rubyrubyruby",
"clojureclojureclojure", "elmelmelm"]
這邊因為 String.duplicate(lang, 3)
在呼叫時需要放入第二的參數
所以不能直接使用 &
抓取
不過這個時候可以使用 &1
來指定要帶入的位置,寫成
&Strig.duplicate(&1, 3)
使用起來會變成
Enum.map(langs, &String.duplicate(&1, 3))
&
也可以從頭開始定義匿名函式搭配()
與 &1
, &2
可以讓它變得跟fn
定義匿名函式一樣功能
adder = &(&1 + &2)
這個等同於
adder = fn x, y -> x + y end
不過這樣不能寫多行,也不能命名參數,但有的時候可以當作簡化寫法