iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
1
Modern Web

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

Day 7 |> 資料的不變性 (Immutability) 以及 模式比較 (Pattern Matching)

  • 分享至 

  • xImage
  •  

資料的不變性 (Immutability)


Elixir是個函數式的程式語言,因此他有一個特性,也就是資料具有不變性
簡單講就是當一個資料被生成後就無法對其進行修改,只能根據舊資料,去作出一個自己需要的新資料。
若放在變數上,也就是: 一但一個變數綁定資料後,是不可修改其資料內容的,除非重新綁定

此外函數式編程還具有一些額外的特點,大家可以看以下這個連結了解一下,或是自己找一下資料。
使用JavaScript學習函式編程

Elixir既然是一個函數式的語言,那自然的有更多語言特性是符合FP開發的,其資料的不變性以及Pattern Matching就是其二,此外,為了處理不可變的資料,Elixir所提供的內置函式,都是不會改變資料本身的純函式。

舉個例子:

Map.put用來將Map中新增一個值,但卻不會修改data本身,而是會回傳一個新增後的Map。

iex(1)> data = %{a: 1}
%{a: 1}
iex(2)> Map.put(data, :b, 2)
%{a: 1, b: 2}
iex(3)> data
%{a: 1} # 資料沒變
iex(4)> data = Map.put(data, :b, 2) # 要這樣寫

若是想在一個List中過濾大於10的值,則是用以下的寫法:

iex(1)> data = [1,3,6,8,32,15]
[1, 3, 6, 8, 32, 15]
iex(2)> data = Enum.filter(data, fn x -> x < 10 end)
[1, 3, 6, 8]

以上就是FP的純函式的使用特性,並且不只在Elixir,在JS以及許多程式語言中,這種寫法以及純函式的觀念已經越來越盛行了。


模式比較 (Pattern Matching)

模式比較是Elixir中一個重要的特性,他可以幫助開發者寫出易讀且簡潔的程式碼。
在Elixir中,等號不只是賦值(雖然前面已經用很多次了,但他不只是那樣),在Elixir中,"=" 代表的是模式比較。
簡單講,他會比較等號兩邊的值是否能夠相等,如果能夠相等,便會讓他相等。

以前面的例子來說:

iex(1)> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex(2)> head
1
iex(3)> tail
[2, 3]

或是

iex(1)> [a, 2, c] = [1, 2, 3]
[1, 2, 3]
iex(2)> a
1
iex(3)> c
3

都是模式比較的用法。
但如果是無法進行匹配時,便會報錯,例如:

iex(5)> [a, 2, a] = [1, 2, 3]
** (MatchError) no match of right hand side value: [1, 2, 3]

因為a在一次 matching 中只能重新進行一次綁定,但沒有任何值可以讓兩邊相等,所以matching失敗。

可使用底線 _ 代替變數,當你不在意他是任何值的時候。

iex(6)> [a, _, _] = [1, 2, "haha"]
[1, 2, "haha"]
iex(7)> a
1

如果你不希望變數被重新綁定,可使用 ^ (pin operator),那不管如何那個變數在這次matching中就不會重新綁定了。

iex(1)> a = 1
1
iex(2)> [^a, 2, 3] = [1, 2, 3]
[1, 2, 3]
iex(3)> a = 2
2
iex(4)> [^a, 2, 3] = [1, 2, 3]
** (MatchError) no match of right hand side value: [1, 2, 3]

或許你會好奇,既然都不要重新綁定了,不會賦值,那為甚麼還要作模式比較,那是因為模式比較除了賦值,也同是能做到"比較",因此有時候也許你的目的不是賦值,而是比較,有時候則是兩者同時。
模式比較配合其他Elixir的語法,可以變出幫助程式碼變得更簡潔易懂,後面章節就會看到。


上一篇
Day 6 |> 集合資料型態 ( Collection ) - Map (映射)
下一篇
Day 8 |> 匿名函式 (Anonymous Function)
系列文
用Elixir學習後端煉金術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言