Alert: 以下會將 Functinoal Programming 簡稱 FP.
yo! What's up
這是筆者第一次參加 IT 鐵人賽,希望可以順利完賽,請大家多多指教!!!
筆者是一位自學程式的前端工程師,一年前,因緣際會下接觸到了 FP,在那之後就與 FP 愛恨糾纏直至今日...
如果把 FP 視為一座山,隨著入山的時間越久,會覺得離山頂的距離越遠,甚至一度想要放棄,但會有種莫名的魔力,吸引你繼續探索,並且這份熱情會越來越強烈,筆者認為這就是 FP 的美妙之處吧!
儘管筆者才剛入山,但還是決定把這近一年的的所學記錄下來,希望能給第一天入山的山友們一點幫助,以及分享這座山的美。
FP 的學習曲線如同下面四種階段 (這是僅是筆者這一年的心境,非每個人都會有這些過程,僅供參考)
蜜月期: 就跟每個人第一次在 terminal 用某個程式語言印出 hello world 的興奮感一樣,FP 剛開始也會給你這種感覺,各種基礎概念很容易就搜尋到,並且這些概念可以快速運用在專案中,這時候成就感爆棚的自己會甚至覺得 FP 也不過如此。但份喜悅不會維持太久,會很快發現自己錯了,而且大錯特錯。
困惑期: 這時候會發現 FP 不是只有 curry, compose, point free 這些 buzz words 這麼簡單,你可能會開始接觸到 functor, monad 這些從 pure FP language 來的 big words, 一開始不知道怎麼去使用它,並且對它一無所知,它會顛覆你對寫程式的認知,是另外一種全新的思維去寫程式。
當 functor, monad 這個概念到 JavaScript 或 TypeScript 時,討論以及寫成文章的人就會相較於 compose, curry 的少很多,也因為 資源密度開始稀疏,所以會讓整個學習過程充滿煎熬,此時會有停滯不前的感覺是很正常的。
絕望期: 儘管知道了 functor, monad 等等的概念,但卻完全不知道如何運用在專案中,並且非 FP 語言實踐 FP 時,不免會有綁手綁腳的感覺,所以會開始學習其他 pure FP language, 例如 haskell, PureScript, clojure 等,而這一切都是為了提升自己的知識廣度,此時也會開始想要理解 FP 的箇中原理,所以會開始學習 category theory 等。 一旦熟悉了這些後,才有可能離開新手村。
創傷後恢復期: 這個時期應該可以稱為融會貫通時期,可以將 FP 的概念落實到各種應用上面,但筆者還沒達到這個境界,或許來年的鐵人賽有幸學成後再來分享。
舉最簡單的例子,像是我們要將一組陣列內的值 乘二 後再取 偶數 。
imperative approach: 是用 step by step 的方式告訴電腦 要如何 達到最終目標,這樣的寫法也使閱讀程式的人需要一段一段地去閱讀。
declarative approach: 是用更抽象的語法,專注於定義所想要的最終目標,不會去管程式該如何做。
// utils
const double = val => val * 2; // 值乘 2
const isEven = val => !(val % 2); // 是否為偶數
// data
const arr = [1, 2, 3, 4, 5];
// imperative approach
let result = [];
for(let i = 0; i < arr.length; i++) {
const doubledVal = double(arr[i]);
if(isEven(doubledVal)) {
result.push(doubledVal)
}
}
console.log(result); // [2, 4, 6, 8, 10]
// declarative approach
const resultF = arr.map(double).filter(isEven);
console.log(resultF) // [2, 4, 6, 8, 10]
可預期的 (Predictability) : 當我們在寫程式時,最害怕的就是發生不可預期的錯誤,而 FP 本身 immutable,以及 pure function 的特性,使我們減少程式內不可預期的結果,也減少了 side effect 的產生。
可複用的 (Reusble) : 每個函式只處理一件事可說是 FP 的一大特色。就好比樂高積木,每一塊積木雖然只有一種功能,但當積木組合起來,就可以讓創造出讓人大吃一驚的模型。並且這些積木可以複用,組出各式各樣的模型。
Functional Programming For Everyone
雖然說這是 Functional Programming For Everyone, 但對於初學 FP 的讀者們,其內容會可能會有點深度,看一次看不懂其實是很正常的,只要持之以恆就可以理解箇中精隨。
而在眾多程式設計典範中, FP 只是其中一種,它沒有任何神奇的魔法,也不會讓開發者一夕之間變成 clean code 大師,甚至會讓其他人覺得這是邪魔歪道,這也是筆者想推廣 FP 的原因之一,它雖然不是萬靈丹(當然也不是邪魔歪道),但可以訓練開發者用另一種思維去寫程式,讓開發者能在開發時多一種強大的武器可以運用。
適合誰:
熟悉 JavaScript, 且對 FP 產生好奇的。
不太適合誰:
不會在 terminal 用任何語言印出 hello world 的讀者們。
文章目標:
推廣 FP 的優點: FP 不得不說,熟練後真的可以讓程式讀起來像是一篇優美的文章,以及達到上面所說的優點。
減少學習 FP 的 Learning Curve: 就如同上述所講的 FP 有一定的學習曲線,而此一挑戰,最低目標就是減少學習者探索資源的時間!
推廣 FP: 取之於社群,回饋於社群。
文章內可能會使用的套件:
Ramda / fp-ts / io-ts
FP 一直都是筆者自我摸索學習的概念,而比較進階的概念甚至不敢用在公司的專案上面,只有用 side project 練習。一方面是 FP 這個 pattern 並不是每個人都耳熟能詳的,怕會造成之後承接專案的開發者維運上的負擔,另一方面也沒有信心有熟練到可以用在專案,希望透過這三十天的分享,梳理這近一年來的所學。
如果看到有寫錯的地方,請不吝嗇地指正。
那我們就開始這三十天的旅程吧!