iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Modern Web

用Elixir學習後端煉金術系列 第 9

Day 9 |> 模組函式 (Named Function)

  • 分享至 

  • xImage
  •  

匿名函式可以有效的作為資料或參數傳遞,有著好用的靈活性。
但我們總是會希望將相同功能的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!"
  • 守衛 (Guard)
    我們可以在模組函式後面加上條件敘述,來限制進行比對的執行,不過guard裡面只支援一些簡單的計算以及elixir允許使用的函式,如is_atom, is_list, abs...等等。
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設定預設值的寫法,加了這個宣告後,這個函式就可以只與一個參數作模式匹配卻擁有預設值。

  • 利用尾遞迴,就可以寫出過去在其他程式語言不敢寫的寫法了,所以我認為這是Elixir一個非常棒的性質。
    不然我們擁有遞迴的思考,卻無法進行遞迴的實作,我覺得是一件很可惜的事,Elixir有限制的讓遞迴實作可以更有效的被使用,讓開發者可以寫出更靈活的程式。

上一篇
Day 8 |> 匿名函式 (Anonymous Function)
下一篇
Day 10 |> 管線運算子 ( Pipe Operator)
系列文
用Elixir學習後端煉金術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言