匿名函式可以有效的作為資料或參數傳遞,有著好用的靈活性。
但我們總是會希望將相同功能的function進行封裝,方便找查與拿來使用,因此才會有模組(Module)的出現。
在Elixri中,模組函式的宣告如下:
defmodule Food do
def eat(), do: "I'm eatting!"
def drink() do
"I'm drinking"
end
end
上面宣告了一個 Food Module 且用兩種寫法(單行和多行),宣告了eat跟drink兩個function。
defmodule Food do
def eat("apple"), do: "I don't like apple!"
def eat(_), do: "I'm eatting!"
end
iex> Food.eat("apple")
"I don't like apple!"
iex> Food.eat("banana")
"I'm eatting!"
defmodule Food do
def eat(food) when food == "apple" , do: "I don't like apple!"
def eat(_), do: "I'm eatting!"
end
iex> Food.eat("apple")
"I don't like apple!"
iex> Food.eat("banana")
"I'm eatting!"
然而在Elixir中有實做尾遞迴這個性質,所以可以在特定情況下使用遞迴的解法來實作函式,因此在codewars裡面,常可以看到網友用遞迴的寫法,寫出很有創意又簡潔的解法,且有合格的效能。
尾遞迴就是說,當一個函式最後的回傳單純只是一個函式時,那他會直接釋放自己的執行空間,並替代成回傳的那個。
舉個計算1~n累加的例子,以下可能是一個寫法
然而我們希望可以達成尾遞迴的條件,sum(n-1) + n並非單純是一個函式的執行,所以這種寫法會造成執行佇列堆疊並爆掉:
defmodule MySum do
def sum(0), do: 0
def sum(n), do: sum(n-1) + n
end
以下式尾遞迴的版本:
defmodule MySum do
def sum(n, sum \\ 0)
def sum(0, sum), do: sum
def sum(n, sum), do: sum(n-1, sum + n)
end
iex> MySum.sum(10)
55
def sum(n, sum \\ 0)
這行是elixir設定預設值的寫法,加了這個宣告後,這個函式就可以只與一個參數作模式匹配卻擁有預設值。