簡介
如果你是一名 JavaScript 開發人員,那麼你很可能會 已經看到過"函數語言程式設計","函子","閉包"或"不變性"等概念了。你可能想知道這些東西到底是什麼意思。也許你已經讀過一些相關資料。或者你可能正在嘗試將一些 FP (Functional Programming) 實踐應用到你的程式碼中。
如果是這樣,那麼我想我們在同一條船上!
大約兩年前,我開始在工作中使用JavaScript。從那時起,我一直在努力加深我對函數語言程式設計的理解。
一開始,每當聽到"柯里化(currying)"之類的東西,或者我的同事告訴我"請使用 map 而不是 forEach 並避免這些副作用"的時候,我感到很迷惑。
從那時開始到現在,我已經學到了很多。試圖理解 FP 實踐是一種非常激動人心的體驗-- 到今天依然如此!
現在,我想把我到目前為止所學到的提煉成一系列文章--一些假如我現在從頭開始學習 FP 的話自己希望能夠讀到的系列文章。我希望這能幫助到那些有跟我幾年前類似程度和背景的人。
什麼是函數語言程式設計?
函數語言程式設計是一種程式設計正規化--- 一種思考和構造程式碼的方式。它是程式式程式設計或物件導向程式設計的替代方案。
FP 愛好者會說他們的目標是優化程式碼的可重用性,可讀性和可測試性。他們工具箱中的常用工具是: 函式(functions),把函式 組合(compose) 起來構建更復雜的功能,以及 避免共享狀態(avoiding shared state) 和 副作用(side effects)。
如果這些話聽起來不知所云 -- 別擔心,我們很快就會搞清楚的!
為什麼要學習函數語言程式設計?
網際網路上有大量的文章討論為什麼函數語言程式設計比物件導向程式設計更好。如何用它生成更易讀,更易於擴充套件,更易於測試和維護的程式碼; 什麼是宣告式(declarative)程式設計,等等。
我同意其中大部分內容。我不想再重複相同的論點,所以我希望你看一下上面的一些連結。
不過,我接下來要講的是另外一些東西。我會告訴你為什麼要考慮學習函數語言程式設計。我會分享一下我的收穫,那也可能將是你的收穫。
1. 它正在成為主流
如果你看一下不斷變化的 JS 生態,很明顯可以看出來函數語言程式設計實踐已經日益普及。大量非常酷的新框架和庫都受到了 FP 的重大影響, 例如:
- React -- 可重用的元件和純函式
- Redux -- 強迫你不要使用可變狀態
- Reason -- 函式式方法和不變性
- Elm -- 可以編譯成 JavaScript 的函式式語言
- Underscore.js,lodash 和 Ramda -- 這幾個庫都內建了 FP
你可能已經或者將要使用這些工具之一。如果你很好地理解了函數語言程式設計的概念,那麼你可以更快地掌握這些框架和庫。否則你可能要多花一些時間。
2. 這很有挑戰性
離開大學之後,你的大腦是不是再也沒有像在學校時那樣全速運轉過了?
我肯定有過。我的意思是,我的工作充滿了挑戰。我花了很多時間思考:業務問題,系統架構,團隊狀態以及許多其他東西。
這並不是說跟上微積分課一樣。學那個的時候我需要絞盡腦汁來理解所有的概念,以及它們之間如何相互關聯。
嗯,學習函數語言程式設計的感覺其實有點兒類似。這也不奇怪,畢竟函數語言程式設計就是來源於數學。
學習過程中會有很多新的術語,理解這些知識可能會讓你頭暈眼花。但是在醍醐灌頂的時刻,你會體會到極大的滿足。
我相信如果你在大學裡喜歡數學,那你肯定也會喜歡學習這些東西的。
哦……這個說法可能不會讓你愛上函數語言程式設計的,對吧?
3. 這是一個新鮮的東西
我相信,即使你不打算在日常工作中切換到函數語言程式設計,學習新的程式設計正規化也是大有好處的。不僅僅是因為這是一個挑戰 -- 更是因為它感覺 很不一樣。
嘗試新的編碼風格可以讓你接觸到另一種截然不同的做事方法。也會迫使你從不同的角度思考問題。
你可能會認為多花一些時間在已經熟練掌握的工具上面更划算。我知道那樣收效更快,更務實,可以讓你的在那些你熟悉的技術上鑽得更深。
但我相信,作為軟體開發者,我們也需要拓寬我們的視野。它有助於我們更好地與其他開發人員溝通,特別是當他們跟我們背景不同的時候。從不同的角度來看問題,可以幫助我們做出更好的決策。
學習新的程式語言是拓寬專業知識的好方法。但是學習新的程式設計正規化更好。
好的,但……為什麼是 JavaScript?
如果你已經決定要學習FP,那麼下一個問題就是:使用 JavaScript 是一個很好的方式嗎?
首先我得說 JavaScript 可能不是學習函數語言程式設計概念的最佳途徑。原因大概有以下這些。
其他更加函式式的語言,內建了不可變資料結構. 而 JavaScript 沒有,因此你需要額外使用一個庫。這樣以來,你的程式碼會比較冗長。
JavaScript 試圖模仿 Java,例如它的 class
,new
,以及其他一些類似的東西。
JavaScript標準庫很糟糕。它當然不是考慮到為 FP 概念而設計的。
關於 JS 是不是函數語言程式設計的最佳選擇,還有很多爭論。
但是另一方面,JavaScript 也有很多特性有助於實現函數語言程式設計:
- 函式在 JS 裡是一等公民 (First-class functions)
- 閉包 (Closures)
- 物件和陣列字面量 (Object and Array Literals) (譯註:參考)
- 大量的 FP 庫
此外,我認為最重要的一點是:JavaScript 非常流行,並且會越來越流行。
如果你打算使用 JavaScript,為什麼不嘗試學習一種非常有用的新正規化呢?
讓我們開始吧!
在本系列的下一部分中,我將介紹一些 FP 概念 - 從最基本的概念開始。我打算涵蓋以下幾個方面:
- 純函式(pure function),一等公民的函式 (first-class functions),高階函式 (Higher-order functions)
- 共享狀態(shared state),不變性(Immutability),副作用(Side effects),引用透明(Referential transparency)
- 閉包(Closures)
- 區域性呼叫(Partial application),柯里化(Currying)
- 遞迴(Recursion)
- 組合(Composition),Point-free 風格
- FP 庫
- 涵子(Functors),Applicative Functors,Monads
我會假定你已經瞭解了 JavaScript 的基礎知識,ES6 等等。對於理解FP概念來說,這並不是一個強制要求。但是,它可以讓你更輕鬆地完成示例並自己做一些嘗試。
準備好了嗎,下一章是:“函式式 JS#2:函式”。