map / filter は reduce で書ける。じゃあ reduce は? mapで書ける。
実用性はないんだけど何となく思いついたので。
ここでは初期値ありバージョンの reduce だけとりあつかいます。
こんな感じ。
const reduce = init => f => xs =>
xs.map( x => init = f(init, x) )[xs.length - 1]
こんな感じで使えます。
// 使用例:
const sum = reduce(0)( (acc, x) => acc + x )
sum([ 1, 2, 3, 4 ]) // 10
分解して考えると:
初期値init、2変数の関数f、配列xs を取り、累算の結果を返す関数reduceを考えます。
累算の一回ごとの途中の値の配列を返す補助的な関数scanを考えると、reduce はこんな風になります。
const reduce = init => f => xs =>
scan(init)(f)(xs)[xs.length - 1]
scanで返ってくる配列の最後の要素が reduce で求めたい値になります。
scanです。
アキュムレータの初期値acc、2変数の関数f、配列xsを取り、累算の一回ごとの値の配列を返します。
const scan = acc => f => xs =>
xs.map( x => acc = f(acc, x) )