點燈坊

失くすものさえない今が強くなるチャンスよ

FP 之 Immutable

Sam Xiao's Avatar 2020-02-01

剛接觸 FP 時,Immutable 是讓我最不可思議的概念,Variable 天生就是拿來給人修改的,但 FP 卻教人 Immutable 不可修改,這是什麼奇怪思想呢 ?

Version

macOS Catalina 10.15.2
VS Code 1.40.2
Quokka 1.0.259
ECMAScript 2015

Mutable

const arr = [1, 2, 3]
arr[0] = 4
arr // ?

ECMAScript 的 primitive 是 immutable,儘管 array 、object 使用了 const 宣告,只是不能 re-assign 而已,依然是 mutable。

也就是嚴格來說,ECMAScript 對於 immutable 支援仍未達 FP 標準。

immutable000

Immutable

回到更基本問題,為什麼需要 immutable 呢 ?

由於 ECMAScript 是 mutable,回想過去經驗,ECMAScript 最令人詬病有三點:

  • 由於 variable 是 mutable,因此常會共用 variable,無論是 global variable,或者是 class 內的 private field,這些雖然使用方便,但由於其他 method 都可修改,卻也是 bug 來源
  • 由於 variable 是 mutable,因此 method 內會伴隨著複雜的 if 判斷如何改變 variable,造成複雜度與維護困難
  • 由於 variable 是 mutable,為了在該 scope 內修改 variable,而造成 method 越寫越大

FP 提出 immutable 概念,variable 只要建立之後就不可修改 !!

也因為不可修改,若結果要改變,只能將 variable 內容讀出,改變後再建立新的 variable,原來 variable 的內容依然不變。

immutable001

若要由 2 變成 30,中間過程須先經過 8,然後 15

Mutable 會直接在同一個 variable 從 2 改成 8,再改成 15,最後再改成 30,完全在同一個 variable 完成。

Immutable 由於 variable 不可修改,會另外建立新的 variable 放 8,然後再建立新的 variable 放 15,最後再建立新的 variable30,一共需要 4 個 variable。

也由於 immutable,由 28,在由 815,最後再由 1530,可發現原本 230 的任務,被切成 3 個小任務:

  • 28
  • 815
  • 1530

而這 3 個小任務剛好就是數學的 y = f(x),也由於 y 的結果只跟 x 有關,因此也稱為 pure function。

而在眾多的小任務中,若發現流程有重複性,可再抽出 higher-order function,只傳入不重複部分即可。

最後可再將 pure function 與 higher-order function 透過 function composition 組合成單一 function。

  • 由於 variable 為 immutable,因此不會再出現共用變數所導致的 bug

  • 由於 variable 為 immutable,因此不再使用複雜的 if 判斷如何改變 variable

  • 也由於大任務被切割成小任務,因此每個 pure function 都很單純都很小,不會再出現大 method

Conclusion

  • 若使用 mutable,除非個人功力極高,否則很難寫出 pure function、higher-order function 與 function composition 架構
  • Immutable 可以算是 pure function 、higher-order function 與 function composition 的催化劑,由於 immutable 無法修改 variable,我們被逼的將修改 variable 的任務切割成眾多小任務而造就 pure function,在重構階段發現重複而抽出 higher-order function,最後再以 function composition 收工

Reference

林信良, 解開對函數式的誤解