實務上常常用到 chain()
,只是一時看不出來而已,可先用已知 Higher Order Function 拆解,最後再重構成 chain()
。
Version
Ramda 0.27.1
pipe()
import { pipe, prop, map, pluck } from 'ramda'
let data = {
books: [
{ title: 'Secrets of the JavaScript Ninja',
authors: [
{ name: 'John Resig' },
{ name: 'Bear Bibeault' }
]
},
{ title: 'RxJS in Action',
authors: [
{ name: 'Paul P.Daniels' },
{ name: 'Luis Atencio' }
]
}
]
}
pipe(
prop('books'),
map(prop('authors')),
map(pluck('name'))
)(data) // ?
data
為 Nested Array,想將所有書的 author
抓出來,最後只有一層 Array。
[ 'John Resig',
'Bear Bibeault',
'Paul P.Daniels',
'Luis Atencio' ]
20 行
pipe(
prop('books'),
map(prop('authors')),
map(pluck('name'))
)(data) // ?
由於是多層 Array,直覺會先用 prop('books')
抓到資料,再使用兩次 map()
。
但結果是兩層 Array,跟我們預期的一層不同。
flatten()
import { pipe, prop, map, pluck, flatten } from 'ramda'
let data = {
books: [
{ title: 'Secrets of the JavaScript Ninja',
authors: [
{ name: 'John Resig' },
{ name: 'Bear Bibeault' }
]
},
{ title: 'RxJS in Action',
authors: [
{ name: 'Paul P.Daniels' },
{ name: 'Luis Atencio' }
]
}
]
}
pipe(
prop('books'),
map(prop('authors')),
flatten,
pluck('name')
)(data) // ?
可先使用 flatten()
攤平一層 Array,再使用 pluck()
,如此最後只剩下一層 Array,這正是我們要的結果。
chain()
import { pipe, prop, pluck, chain } from 'ramda'
let data = {
books: [
{ title: 'Secrets of the JavaScript Ninja',
authors: [
{ name: 'John Resig' },
{ name: 'Bear Bibeault' }
]
},
{ title: 'RxJS in Action',
authors: [
{ name: 'Paul P.Daniels' },
{ name: 'Luis Atencio' }
]
}
]
}
pipe(
prop('books'),
chain(prop('authors')),
pluck('name')
)(data) // ?
pipe(map, flatten)
相當於 chain()
,因此可用 chain()
加以化簡。
chain()
(a → b) → [a] → [b]
相當於flatten()
與map()
組合
(a -> b)
:相當於 map function
[a]
:data 為 Array
[b]
:回傳攤平後的 Array
Conclusion
- 只要是多層 Array,使用
chain()
的機會就很高,若一時看不出來,可先使用map()
,發現多了一層,再使用flatten()
攤平,當看到pipe(map, flatten)
時,就會聯想到使用chain()
重構