Ramda 提供了 propEq()
,專門產生比較 Property 是否 相等
的 Predicate,若 不等
呢 ? 理論上可以自己組合出新 Function,Wink-fp 已經提供 propNEq()
可直接使用。
Version
macOS Catalina 10.15.3
Wink-fp 1.23.2
filter()
import { filter } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// f :: a -> [Object] -> [Object]
let f = v => filter(x => x.title !== v)
f('Speaking JavaScript')(data) // ?
第 9 行
// f :: a -> [Object] -> [Object]
let f = v => filter(x => x.title !== v)
我們想找出所有 title 不是
Speaking JavaScript 的書,若使用 filter()
,勢必使用 反向邏輯
,也就是 !==
。
not()
import { pipe, filter, propEq, not } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// f :: a -> [Object] -> [Object]
let f = v => filter(pipe(propEq('title', v), not))
f('Speaking JavaScript')(data) // ?
第 9 行
// f :: a -> [Object] -> [Object]
let f = v => filter(pipe(propEq('title', v), not))
使用 pipe()
將 propEq()
與 not()
組合起來,使 filter()
的 predicate 能 point-free。
complement()
import { filter, propEq, complement } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// f :: a -> [Object] -> [Object]
let f = v => filter(complement(propEq)('title', v))
f('Speaking JavaScript')(data) // ?
第 9 行
// f :: a -> [Object] -> [Object]
let f = v => filter(complement(propEq)('title', v))
也可使用 propEq()
取 complement()
,這也能使 filter()
的 predicate 能 point-free。
propNEq()
import { filter, propEq, complement } from 'ramda';
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// propNEq :: String -> a -> Object -> Boolean
let propNEq = complement(propEq)
// f :: a -> [Object] -> [Object]
let f = v => filter(propNEq('title', v))
f('Speaking JavaScript')(data) // ?
第 9 行
// propNEq :: String -> a -> Object -> Boolean
let propNEq = complement(propEq)
若要模仿 propEq()
而有 propNEq()
,可使用 complement()
與 propEq()
組合。
12 行
// f :: a -> [Object] -> [Object]
let f = v => filter(propNEq('title', v))
如此在 filter()
內能簡單地使用 propNEq()
。
Wink-fp
import { filter } from 'ramda'
import { propNEq } from 'wink-fp'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// f :: a -> [Object] -> [Object]
let f = v => filter(propNEq('title', v))
f('Speaking JavaScript')(data) // ?
Wink-fp 已經提供 propNEq()
可直接使用。
propNEq()
String -> a -> Object -> Boolean
判斷指定 Object 的 property 是否不等於該值
String
:提供 Object 的 property
a
:提供任意要比較的值
Object
:data 為 Object
Boolean
:若不相等則傳回 true
,否則回傳 false
Function Pipeline
import { pipe, filter } from 'ramda'
import { propNEq } from 'wink-fp'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// f :: a -> [Object] -> [Object]
let f = pipe(
propNEq('title'),
filter
)
f('Speaking JavaScript')(data) // ?
10 行
// f :: a -> [Object] -> [Object]
let f = pipe(
propNEq('title'),
filter
)
有了 propNEq()
之後就可輕易組合 filter()
與 propNEq()
,使 f()
也能 point-free。
Conclusion
- 寫程式盡量避免
反向邏輯
,應優先使用正向邏輯
的 function,若不得已要使用反向邏輯
,則 Wink-fp 的propNEq()
讓我們不必每次都自行組合propEq()
與complement()
Reference
Ramda, filter()
Ramda, propEq()
Ramda, not()
Ramda, pipe()
Ramda, complement()