iT邦幫忙

2021 iThome 鐵人賽

DAY 1
1
Software Development

Functional Programming For Everyone系列 第 1

Day 01 - Hi, Functional Programming

Alert: 以下會將 Functinoal Programming 簡稱 FP.

關於我

yo! What's up

這是筆者第一次參加 IT 鐵人賽,希望可以順利完賽,請大家多多指教!!!

筆者是一位自學程式的前端工程師,一年前,因緣際會下接觸到了 FP,在那之後就與 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 的概念落實到各種應用上面,但筆者還沒達到這個境界,或許來年的鐵人賽有幸學成後再來分享。

FP 的優點

  • 可讀性 (Readability): FP 相較於 imperative programming 有著更佳的可讀性。而可讀性帶來的好處,不僅僅可以減少寫程式犯錯機會,也可以讓讀程式碼的人,更舒服地理解該段程式在處理什麼邏輯。

舉最簡單的例子,像是我們要將一組陣列內的值 乘二 後再取 偶數

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 的原因之一,它雖然不是萬靈丹(當然也不是邪魔歪道),但可以訓練開發者用另一種思維去寫程式,讓開發者能在開發時多一種強大的武器可以運用。

目前文章規劃大概會:

  1. Functional Thinking 基礎概念 (Day 2 ~ Day 5)
  2. Functional Thinking 進階概念 (Day 6 - Day 8)
  3. Functional Programming fundamental (Day 9 - Day 15)
  4. ADTs (Day 17 - Day 24)
  5. 實作小專案 (Day 25 - Day 29)
  6. 總結 (Day 30)

給讀者們:

適合誰:
熟悉 JavaScript, 且對 FP 產生好奇的。

不太適合誰:
不會在 terminal 用任何語言印出 hello world 的讀者們。

文章目標:

  • 推廣 FP 的優點: FP 不得不說,熟練後真的可以讓程式讀起來像是一篇優美的文章,以及達到上面所說的優點。

  • 減少學習 FP 的 Learning Curve: 就如同上述所講的 FP 有一定的學習曲線,而此一挑戰,最低目標就是減少學習者探索資源的時間!

  • 推廣 FP: 取之於社群,回饋於社群。

文章內可能會使用的套件:
Ramda / fp-ts / io-ts

小結

FP 一直都是筆者自我摸索學習的概念,而比較進階的概念甚至不敢用在公司的專案上面,只有用 side project 練習。一方面是 FP 這個 pattern 並不是每個人都耳熟能詳的,怕會造成之後承接專案的開發者維運上的負擔,另一方面也沒有信心有熟練到可以用在專案,希望透過這三十天的分享,梳理這近一年來的所學。

如果看到有寫錯的地方,請不吝嗇地指正。

那我們就開始這三十天的旅程吧!


下一篇
Day02 - Pure Function
系列文
Functional Programming For Everyone30

1 則留言

0
Ken Chen
iT邦新手 5 級 ‧ 2021-09-16 21:55:53

正在困惑期,期待大大後續的分享~~~

我要留言

立即登入留言