iT邦幫忙

2025 iThome 鐵人賽

DAY 2
0

在第一篇我們說到會介紹一點 functional programming (FP) ,不過不用太緊張,我們不會很深入 FP 的概念,我想應該有不少人,看了一些 FP 的教學,結果馬上就看到 Monad 這個不知道那是什麼的東西,就讀不下去了

但不用擔心,你不需要知道什麼是 Monad 也可以使用 Effect ,而且我也不會介紹到那些專有名詞

所以什麼是 Functional Programming

數學上的函數是指給一輸入,經函數的計算後,會被對應到另一個值

https://ithelp.ithome.com.tw/upload/images/20250916/20111802AHs91hWtWG.png

像上面的函數就是當 x 輸入 1 ,則你會拿到 2 ,輸入 2 會拿到 4 ,輸出的值會等於輸入的值乘以 2 ,以程式碼表示就變成

function f(x: number) {
  return x * 2
}

我們再來看一下比較複雜的範例,如果我們要對一個數字陣列,每個值都乘以 2 ,其中一個寫法會是像這樣

function allTimesTwo(input: number[]) {
  const result = []
  for (const item of input) {
    result.push(item * 2)
  }
  return result
}

那如果要對每個元素加 1 呢?

function allPlusOne(input: number[]) {
  const result = []
  for (const item of input) {
    result.push(item + 1)
  }
  return result
}

有沒有注意到,除了中間的 item * 2item + 1 不同外,其它的部份都一樣,那我們有沒有可能將中間的部份單獨抽出來,答案是有的,我們可以將中間的部份變成一個 function 傳入

function allDoSomething(input: number[], f: (item: number) => number) {
  const result = []
  for (const item of input) {
	result.push(f(item))
  }
  return result
}

使用上就只需要像這樣

allDoSomething(list, (item) => item * 2) // 這個相當於 allTimesTwo
allDoSomething(list, (item) => item + 1) // 這個相當於 allPlusOne

不知道這樣有沒有讓你想到,在原生的 JavaScript 中,我們可能會像這樣處理

list.map((item) => item * 2) 
list.map((item) => item + 1)

那如果要先乘以 2 再都加 1 呢?

list
  .map((item) => item * 2)
  .map((item) => item + 1)

這上面展示了兩個 FP (Functional Programming) 的概念

  1. Function is first-class citizen: Function 也可以當作一種資料型態,也可以當作參數
  2. 將任務拆成一個一個小步驟,將步驟組合起來完成

所以這跟 Effect 有什麼關係

Effect 是一個比較偏向 FP 的套件,官方也做了很多方便 FP 開發的設計,比如

  1. 大部份的功能都是 function ,而且 function 就是專注在一個任務上
  2. 大部份的 function 都同時支援 data-first 與 data-last 的寫法

什麼是 data-first 與 data-last

以上面 allDoSomething而言

data-first:

allDoSomething(list, (item) => item * 2)

data-last:

allDoSomething((item) => item * 2, list)

像這樣看資料是放在第一個參數還是最後一個參數,而 Effect 的 function 還有進一步的設計,讓你可以像這樣呼叫

allDoSomething((item) => item * 2)(list)

另外搭配一個內建的 pipe 的 function ,pipe 會把第一個參數傳給下一個 function ,並把第一個 function 的結果再傳給第二個 function ,依此類推,會變的像這樣

pipe(
  list,
  allDoSomething((item) => item * 2),
  allDoSomething((item) => item + 1),
)

這代表的是都先乘 2 再加 1 ,之後我們很可能會看到這樣的寫法

下一篇要來介紹的是為什麼我們需要 Effect

Reference


上一篇
0. Effect 魔法:替你的應用程式注入堅不可摧的力量
下一篇
2. 為什麼需要 Effect, Promise 不夠嗎
系列文
Effect 魔法:打造堅不可摧的應用程式5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言