iT邦幫忙

2023 iThome 鐵人賽

DAY 5
1

今天的目標是用 function 讓資料模型「動」起來。想像一個 function 串著一個 function ,把資料揉揉捏捏,經過一道道工序的處理最後變成我們想要的樣子,聽起來就很棒對吧 \(^∀^)メ(^∀^)ノ

https://ithelp.ithome.com.tw/upload/images/20230920/20158615PErfFCUWqx.png

我們同樣用課程名稱的輸入來舉例

  1. 當使用者輸入課程名稱,每打一個字就會觸發一次 ui event
  2. 每次出現 ui event,我們掛在 event hook 的 function 就會被呼叫,這時候我們要做的就是把React event (例如輸入改變事件) 轉換成我們剛剛設計的 domain type (課程名稱)
  3. 為了方便跨元件狀態共享,我們使用 Atom 來管理我們的 domain type (Atom 來自 Jotai)
  4. 每次 Atom 所管理的 domain type 被改變都會讓有使用這個 domain type 的 component 被重新渲染,使得更新後的 domain type 能轉換成參數傳遞到所屬的子元件,完成畫面的更新。

實際上不只是課程名稱,整個表單的驗證都只需要遵循步驟一到步驟四就可以完成 !

如果你不熟悉 React 還有 Atom,可能會覺得有點抽象,不過這很正常,沒有關係,多看看多寫寫就會了

Function ! 組合 !

把上面的文字轉換後,我們可以用以下兩個 function 來組成 function A

type getInputString = (event:ChangeEvent) => string // 從輸入事件取出字串
type courseNameOf = (input:string) => CourseName // 把字串傳換成先前定義的資料模型

可是 ... 該怎麼把這兩個 function 組合在一起做呢 ?

https://ithelp.ithome.com.tw/upload/images/20230920/20158615rlqs2HXllp.jpg
來源

照一般原生寫法我們會寫成這樣

const input = getInputString(event)
const name = courseNameOf(input)

看起來沒有甚麼問題,可是如果想要組合的 function 變多會發生甚麼事呢 ?

https://ithelp.ithome.com.tw/upload/images/20230920/20158615e3gGeVcELm.png
來源

const temp1 = add7(3)
const temp2 = exp2(temp1)
const temp3 = sub2(temp2)
const result = mul5(temp3)

無意義的變數命名好累好麻煩(T▽T)

const result = mul5(sub2(exp2(add7(3))))

省略掉變數以後,閱讀順序怪怪的不太自然,還要加上很多括號,好像更糟糕了 (T▽T)

https://ithelp.ithome.com.tw/upload/images/20230920/201586151OCWPbxw33.png
來源

pipe

為了解決以上問題,pipe 就出現啦 ! 有了 pipe 以後,多個 function 的組合看起來會像這樣

import { pipe } from 'effect/Function'

const result = pipe(1, add7, exp2, sub2, mul5) 

課程名稱的範例則會像這樣

const courseName = (event:ChnageEvent)=>pipe(event, getInputString, courseNameOf)

我們之後會常常用到這種語法,克服習慣問題以後,會發現看起來很舒服唷 (^ω^)

flow

在使用 pipe 的時候常常會發現如下圖 calculate function 的輸入參數等於 pipe 的第一個參數的情形

const calculate = (input:number)=>pipe(input, add7, exp2, sub2, mul5)

這時候我們可以用 flow 來取代重複出現的 input,看起來又更簡潔了!

import { flow } from 'effect/Function'

const calculate = flow(add7, exp2, sub2, mul5)

更多 FP buzzwords

講完 pipe 跟 flow 聯想到兩個酷酷的術語跟大家分享。

https://ithelp.ithome.com.tw/upload/images/20230920/20158615vnp2bvHvKV.png
來源

flow 或 pipe 和其他的範例 function 不太一樣,這是因為它們把 function 當作輸入或是輸出了,這代表他們是 higher order function

Higher-order function
指某個 function 滿足以下任一條件

  1. 把其他 function 作為參數傳入
  2. 把其他 function 做回回傳值傳出

在 js 語言中 function 是一等公民,因為它符合以下定義

Functions are first-class citizen
指在某個語言中,function 像其他物件一樣可以作為變數儲存、作為參數傳遞、作為 function 的回傳值回傳。

在寫 JS 的時候我們可以把 function 當作參數丟進去一個 higher order funciton 產生另一個 function,真是太有趣了,對吧 ..... ?


上一篇
D04 - 設計資料模型
下一篇
D06 - 測試驅動開發
系列文
從 Next.js 開始的 Functional Programming 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言