Vuex 的 Getter,其 State 與 Getter 都是以 Object 傳入,因此特別適合使用 Ramda 的 useWith()
使 Getter 加以 Point-free。
Version
macOS Mojave 10.14.6
Vue 2.6.10
Vuex 3.0.1
Ramda 0.26.1
Scenario 1
Normal Getter
let price = ({ isDiscount }, { price }) => isDiscount ? price : 0;
一個典型的 getter,state 與 getter 都是由參數傳入,我們會直接使用 destructing 在 argument list 拆解,且使用了 ?:
ternary operator。
Point-free
import { useWith, ifElse, nthArg, always, prop } from 'ramda';
let price = useWith(
ifElse(nthArg(0), nthArg(1), always(0)), [
prop('isDiscount'),
prop('price')
]
);
price()
主角為 isDiscount ? price : 0
,此為 main function,在執行 main function 之前,必須透過 destructing 將傳進來的 state 與 getter 拆解,這正適合 useWith()
:
- 使用
useWith()
先透過prop()
transformer function 將傳進來的 getter 與 setter 拆解 - 將拆解後的值傳給
isShipable ? shipFare : 0
執行 ?:
ternary operator 可改用ifElse()
,傳進來的參數可改用nthArg()
獲得
如此 price()
getter 就被 useWith()
加以 Point-free 了。
useWith()
((x1, x2, ...) -> z) -> [(a -> x1), (b -> x2), ...] -> (a -> b -> ... -> z)
建立一個與 main function 參數個數相同的新 function,且各參數會先經過 transformer function 處理過再傳給 main function 執行
Scenario 2
Normal Getter
let cash = ({ cash }, { amount }) => (cash >= amount) ? amount : cash;
與 use case 1 極為類似,差異在於 ?:
ternary operator 的判斷再加碼使用 >=
。
Point-free
let cash = useWith(
ifElse(gte, nthArg(1), nthArg(0)), [
prop('cash'),
prop('totalAmount'),
],
);
一樣使用 useWith()
與 ifElse()
。
差異在於 ifElse()
目前不是接 nthArg(0)
,而是接 gte()
,這相當於 >=
,由於 gte()
本來就是兩個參數,因此直接接收兩個 transformer funciton 的回傳值。
gte()
Ord a => a → a → Boolean
若第一個參數大於第二個參數則傳回true
,否則傳回false
Conclusion
- 當參數為 object 時或 Vuex 的 getter 時,必須先對 object 加以拆解才能繼續使用,此時很適合使用
useWith()
透過 transformer function 加以處理,最後再傳給 main function
Reference
Ramda, useWith()
Ramda, ifElse()
Ramda, nthArg()
Ramda, prop()
Ramda, gte()