UNPKG

rubico

Version:

[a]synchronous functional programming

86 lines (82 loc) 2.85 kB
const __ = require('./placeholder') const arrayPush = require('./arrayPush') const always = require('./always') const curry2 = require('./curry2') const getArg1 = require('./getArg1') const identity = require('./identity') const isArray = require('./isArray') const isPromise = require('./isPromise') const promiseAll = require('./promiseAll') const funcConcatSync = require('./funcConcatSync') const asyncIteratorForEach = require('./asyncIteratorForEach') const symbolIterator = require('./symbolIterator') const symbolAsyncIterator = require('./symbolAsyncIterator') /** * @name arrayFlatten * * @synopsis * ```coffeescript [specscript] * Stream<T> = { read: ()=>T, write: T=>() } * Monad<T> = Array<T>|String<T>|Set<T> * |TypedArray<T>|Stream<T>|Iterator<Promise|T> * |{ chain: T=>Monad<T> }|{ flatMap: T=>Monad<T> }|Object<T> * Reducer<T> = (any, T)=>Promise|any * Foldable<T> = Iterable<T>|AsyncIterable<T>|{ reduce: Reducer<T> }|Object<T> * * arrayFlatten< * T any, * array Array<Monad<T>|Foldable<T>|T> * >(array) -> Array<T> * ``` */ const arrayFlatten = function (array) { const length = array.length, promises = [], result = [] let index = -1 while (++index < length) { const item = array[index] if (isArray(item)) { const itemLength = item.length let itemIndex = -1 while (++itemIndex < itemLength) { result.push(item[itemIndex]) } } else if (item == null) { result.push(item) } else if (typeof item.then == 'function') { promises.push(item.then(curry2(arrayPush, result, __))) } else if (typeof item[symbolIterator] == 'function') { for (const subItem of item) { result.push(subItem) } } else if (typeof item[symbolAsyncIterator] == 'function') { promises.push(asyncIteratorForEach( item[symbolAsyncIterator](), curry2(arrayPush, result, __))) } else if (typeof item.chain == 'function') { const monadValue = item.chain(identity) isPromise(monadValue) ? promises.push(monadValue.then(curry2(arrayPush, result, __))) : result.push(monadValue) } else if (typeof item.flatMap == 'function') { const monadValue = item.flatMap(identity) isPromise(monadValue) ? promises.push(monadValue.then(curry2(arrayPush, result, __))) : result.push(monadValue) } else if (typeof item.reduce == 'function') { const folded = item.reduce(funcConcatSync( getArg1, curry2(arrayPush, result, __)), null) isPromise(folded) && promises.push(folded) } else if (item.constructor == Object) { for (const key in item) { result.push(item[key]) } } else { result.push(item) } } return promises.length == 0 ? result : promiseAll(promises).then(always(result)) } module.exports = arrayFlatten