由於 Vue 3 支援 Composition API,不只 Function Pipeline 與 Point-free 得以實現,如 FP 慣用的 Maybe 在 Vue 3 裡也得以發揮。
Version
Vue 3.0.11
Sanctuary 3.1.0
Array.prototype.find
輸入書本名稱,若找不到則顯示 N/A
。
若找得到則顯示其 price。
<template lang='pug'>
input(v-model='title')
button(@click='onClick') Submit
span {{ price }}
</template>
<script setup>
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'Elm in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
ref: title = ''
ref: price = ''
let onClick = () => {
let result = data.find(x => x.title === title)
if (result) price = result.price
else price = 'N/A'
}
</script>
第 8 行
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'Elm in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
資料定義在 data
,若輸入 FP in JavaScript
,將顯示 100
。
17 行
let onClick = () => {
let result = data.find(x => x.title === title)
if (result) price = result.price
else price = 'N/A'
}
使用了 ECMAScript 的 Array.prototype.find
,若找到則回傳 Object,若找不到則回傳 undefined
。
由於致命的
undefined
,這使得 Method Chaining 中斷,必須回到 Imperative 使用if
判斷
Maybe
結果不變,但使用 Maybe 改寫。
<template lang='pug'>
input(v-model='title')
button(@click='onClick') Submit
span {{ price }}
</template>
<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, propEq, map, always } from 'ramda'
import { find, prop, flip, create, env } from 'sanctuary'
let { maybe, I } = create({ checkTypes: false, env })
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'Elm in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let title = ref ('')
let price = ref ('')
let onClick = pipe (
read (title),
propEq ('title'),
flip (find) (data),
map (prop ('price')),
maybe ('N/A') (I),
write (price)
)
</script>
24 行
let onClick = pipe (
read (title),
propEq ('title'),
flip (find) (data),
map (prop ('price')),
maybe ('N/A') (I),
write (price)
)
使用 pipe
組合 onClick
:
read (title)
:讀取title
statepropEq ('title')
:組合find
所需 callbackflip (find) (data)
:與Array.prototype.find
的差異是無論找不找得到都會傳 Maybe,因此不用擔心undefined
問題map (prop ('price'))
:從 Just 內讀取出price
maybe ('N/A') (I)
:若是 Nothing 則回傳N/A
,Just 則回傳 Maybe 內部值write (price)
:最後寫入price
state
可發現 Maybe 不必在商業邏輯中間使用
if
中斷,全部過程都是 happy path,只要在最後寫入 side effect 前以maybe
從 Maybe 內取出值即可
Conclusion
- 當使用 Sanctuary 的
find
時,若要搭配flip
,記得要使用 Sanctuary 的flip
,而不能使用 Ramda 的flip
,否則無法真正確翻轉find
的 argument - 可發現由於 Sanctuary 的
find
回傳 Maybe,因此很平順的在 Function Pipeline 使用,完全不用搭配 Imperative 的if
做判斷,完全發揮 Vue 3 的 Composition API 優點