由於 Vue 3 支援 Composition API,不只 Function Pipeline 與 Point-free 得以實現,如 FP 慣用的 Either 在 Vue 3 也得以發揮。
Version
Vue 3.0.11
Sanctuary 3.1.0
Either
輸入一般值會計算出結果。
輸入 0
時會直接顯示 Exception 訊息。
<template lang='pug'>
input(v-model='num')
button(@click='onClick') Submit
span {{ result }}
</template>
<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe } from 'ramda'
import { Left, Right, map, add, either, I } from 'sanctuary'
let num = ref(0)
let result = ref('')
let div = x => y =>
y === 0 ?
Left('Can not divide by zero') :
Right(x / y)
let onClick = pipe(
read(num),
div(2),
map(add(1)),
either(I)(I),
write(result)
)
</script>
16 行
let div = x => y =>
y === 0 ?
Left('Can not divide by zero') :
Right(x / y)
自行實作 div()
,當 /0
時回傳 Left Either,正常結果則回傳 Right Either。
21 行
let onClick = pipe(
read(num),
div(2),
map(add(1)),
either(I)(I),
write(result)
)
使用 pipe()
組合出 onClick()
:
read(num)
:讀取num
statediv(2)
:計算除法map(add(1))
:使用add()
計算加法,因為div()
回傳 Either,所以add()
須在map()
內either(I)(I)
:使用either(I)(I)
取出 Either 內部值write(result)
:寫入result
state
可發現
div()
雖然可能發出 Exception,但不會因此中斷 Function Pipeline,且後續計算都可維持在 Either 內,只要最後從 Either 內部取出值即可
Promise
結果不變,但使用 Promise 模擬 Either 改寫。
<template lang='pug'>
input(v-model='num')
button(@click='onClick') Submit
span {{ result }}
</template>
<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, andThen as then, otherwise, add } from 'ramda'
import { reject, resolve } from 'wink-fp'
let num = ref(0)
let result = ref('')
let div = x => y =>
y === 0 ?
reject('Can not divide by zero') :
resolve(x / y)
let onClick = pipe(
read(num),
div(2),
then(add(1)),
then(write(result)),
otherwise(write(result))
)
</script>
16 行
let div = x => y =>
y === 0 ?
reject('Can not divide by zero') :
resolve(x / y)
將 Exception 訊息改包在 Rejected Promise 內,正常值則包在 Fulfilled Promise。
21 行
let onClick = pipe(
read(num),
div(2),
then(add(1)),
then(write(result)),
otherwise(write(result))
)
使用 pipe()
組合出 onClick()
:
read(num)
:讀取num
statediv(2)
:計算除法then(div(1))
:使用add()
計算加法,因為div()
回傳 Promise,所以add()
須在then()
內then(write(result))
:取出 Resolved Promise 並寫入result
stateotherwise(write(result))
:取出 Rejected Promise 並寫入result
state
使用 Promise 取代 Either 後,後續 function 都必須在
then()
內,且最後使用then()
取出 Resolved Promise,使用otherwise()
取出 Rejected Promise
Conclusion
- 若
div()
使用傳統 Exception,則無法在 Function Pipeline 使用,必須回到 Imperative 寫法 - 若改用 Either 或 Promise 回傳 Exception,配合 Vue 3 的 Composition API 則可順利以 Point-free 組合出
onClick()
- 雖然可以使用 Promise 模擬 Either,但實務上還是建議直接使用 Either 語意較佳