reduce()
為 FP 代表性 Function,與 Array.prototype.reduce()
功能相同;唯內建的 reduce()
是以 OOP 掛在 Array 上,而 Ramda 的 reduce()
是以 FP 將 Array 傳入最後一個參數。
Version
macOS Mojave 10.15.2
VS Code 1.41.1
Quokka 1.0.274
Ramda 0.26.1
Imperative
let data = [30, 80, 20, 40, 25]
let reduce = fn => init => arr => {
let a = init
for(let x of arr)
a = fn(a, x)
return a
}
let reducer = (a, x) => a >= x ? a - x : a
reduce(reducer)(100)(data) // ?
帳戶內有 100
元,data
為陸續所提出的金額。
- 若提出後
餘額
大於等於0
,則可
提出該金額,並繼續下一筆 - 若提出後
餘額
小於0
,則不可
提出該金額,並繼續下一筆 - 最後回傳帳戶剩餘金額
Imperative 會使用 for
loop,以初始值 init
建立好回傳的 a
,並使用傳入的 function 計算結果,最後回傳 a
結束執行。
reduce()
let data = [30, 80, 20, 40, 25]
let reduce = fn => init => arr => arr.reduce(fn, init)
let reducer = (a, x) => a >= x ? a - x : a
reduce(reducer)(100)(data) // ?
Array.prototype
已經內建 reduce()
,可直接使用。
Ramda
import { reduce } from 'ramda'
let data = [30, 80, 20, 40, 25]
let reducer = (a, x) => a > x ? a - x : a
reduce(reducer)(100)(data) // ?
Ramda 也提供了 reduce()
,可使其 point-free。
reduce()
((a, b) → a) → a → [b] → a
將 array 轉變為單一 value 或 object
((a, b) → a)
:reducer function,運算 accumulator 與 value 關係
a
:accumulator,每個 iteration 的累計值
[b]
:data 為 array
a
:最後累計值
Conclusion
- 很多初學者視
reduce()
為畏途,其實只要自己用 imperative 實作一次reduce()
,就可發現它只是將重複的部分抽成 higher order function,不重複部分以 function 傳入而已 - 只要
for
loop 寫的出來,理論上reduce()
都寫得出來,但應優先使用 higher order function 組合,除非真的組合不出來,最後才使用reduce()
- Ramda 的
reduce()
與Array.prototype.reduce()
相同,差異只在 data 位置而已