rubico
Version:
[a]synchronous functional programming
80 lines (76 loc) • 2.67 kB
JavaScript
const isArray = require('./isArray')
const objectValues = require('./objectValues')
const isGeneratorFunction = require('./isGeneratorFunction')
const isAsyncGeneratorFunction = require('./isAsyncGeneratorFunction')
const iteratorReduce = require('./iteratorReduce')
const asyncIteratorReduce = require('./asyncIteratorReduce')
const symbolIterator = require('./symbolIterator')
const symbolAsyncIterator = require('./symbolAsyncIterator')
const __ = require('./placeholder')
const curry2 = require('./curry2')
const curryArgs3 = require('./curryArgs3')
const arrayReduce = require('./arrayReduce')
const objectReduce = require('./objectReduce')
const mapReduce = require('./mapReduce')
const reducerConcat = require('./reducerConcat')
/**
* @name genericReduce
*
* @synopsis
* ```coffeescript [specscript]
* Foldable<T> = Iterable<T>|AsyncIterable<T>
* |{ reduce: (any, T)=>any }|Object<T>
*
* genericReduce<T>(
* collection Foldable<T>,
* reducer (any, T)=>any,
* result any?,
* ) -> result
* ```
*
* @related genericReduceConcurrent
*
* @TODO genericReduceSync(collection, reducer, init) - performance optimization for some of these genericReduces that we know are synchronous
*
* @TODO genericReducePool(poolSize, collection, reducer, init) - for some of these genericReduces that we want to race - result should not care about order of concatenations
* reduce.pool
* transform.pool
* flatMap.pool
*/
const genericReduce = function (collection, reducer, result) {
if (isArray(collection)) {
return arrayReduce(collection, reducer, result)
}
if (collection == null) {
return result === undefined
? curry2(reducer, collection, __)
: reducer(result, collection)
}
if (collection.constructor == Map) {
return mapReduce(collection, reducer, result)
}
if (typeof collection[symbolIterator] == 'function') {
return iteratorReduce(
collection[symbolIterator](), reducer, result)
}
if (typeof collection[symbolAsyncIterator] == 'function') {
return asyncIteratorReduce(
collection[symbolAsyncIterator](), reducer, result)
}
if (typeof collection.reduce == 'function') {
return collection.reduce(reducer, result)
}
if (typeof collection.chain == 'function') {
return collection.chain(curry2(reducer, result, __))
}
if (typeof collection.flatMap == 'function') {
return collection.flatMap(curry2(reducer, result, __))
}
if (collection.constructor == Object) {
return objectReduce(collection, reducer, result)
}
return result === undefined
? curry2(reducer, collection, __)
: reducer(result, collection)
}
module.exports = genericReduce