UNPKG

ramda.reduce

Version:

R.reduce exported as a module

330 lines (307 loc) 11.4 kB
// Ramda v0.26.1 // https://github.com/ramda/ramda // (c) 2013-2019 Scott Sauyet, Michael Hurley, and David Chambers // Ramda may be freely distributed under the MIT license. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.R = {}))); }(this, (function (exports) { 'use strict'; function _isPlaceholder(a) { return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true; } /** * Optimized internal one-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry1(fn) { return function f1(a) { if (arguments.length === 0 || _isPlaceholder(a)) { return f1; } else { return fn.apply(this, arguments); } }; } /** * Optimized internal two-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry2(fn) { return function f2(a, b) { switch (arguments.length) { case 0: return f2; case 1: return _isPlaceholder(a) ? f2 : _curry1(function(_b) { return fn(a, _b); }); default: return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function(_a) { return fn(_a, b); }) : _isPlaceholder(b) ? _curry1(function(_b) { return fn(a, _b); }) : fn(a, b); } }; } /** * Optimized internal three-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry3(fn) { return function f3(a, b, c) { switch (arguments.length) { case 0: return f3; case 1: return _isPlaceholder(a) ? f3 : _curry2(function(_b, _c) { return fn(a, _b, _c); }); case 2: return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function(_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) ? _curry2(function(_b, _c) { return fn(a, _b, _c); }) : _curry1(function(_c) { return fn(a, b, _c); }); default: return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function(_a, _b) { return fn(_a, _b, c); }) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function(_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function(_b, _c) { return fn(a, _b, _c); }) : _isPlaceholder(a) ? _curry1(function(_a) { return fn(_a, b, c); }) : _isPlaceholder(b) ? _curry1(function(_b) { return fn(a, _b, c); }) : _isPlaceholder(c) ? _curry1(function(_c) { return fn(a, b, _c); }) : fn(a, b, c); } }; } /** * Tests whether or not an object is an array. * * @private * @param {*} val The object to test. * @return {Boolean} `true` if `val` is an array, `false` otherwise. * @example * * _isArray([]); //=> true * _isArray(null); //=> false * _isArray({}); //=> false */ var _isArray = Array.isArray || function _isArray(val) { return (val != null && val.length >= 0 && Object.prototype.toString.call(val) === '[object Array]'); }; function _isString(x) { return Object.prototype.toString.call(x) === '[object String]'; } /** * Tests whether or not an object is similar to an array. * * @private * @category Type * @category List * @sig * -> Boolean * @param {*} x The object to test. * @return {Boolean} `true` if `x` has a numeric length property and extreme indices defined; `false` otherwise. * @example * * _isArrayLike([]); //=> true * _isArrayLike(true); //=> false * _isArrayLike({}); //=> false * _isArrayLike({length: 10}); //=> false * _isArrayLike({0: 'zero', 9: 'nine', length: 10}); //=> true */ var _isArrayLike = _curry1(function isArrayLike(x) { if (_isArray(x)) { return true; } if (!x) { return false; } if (typeof x !== 'object') { return false; } if (_isString(x)) { return false; } if (x.nodeType === 1) { return !!x.length; } if (x.length === 0) { return true; } if (x.length > 0) { return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1); } return false; }); function XWrap(fn) { this.f = fn; } XWrap.prototype['@@transducer/init'] = function() { throw new Error('init not implemented on XWrap'); }; XWrap.prototype['@@transducer/result'] = function(acc) { return acc; }; XWrap.prototype['@@transducer/step'] = function(acc, x) { return this.f(acc, x); }; function _xwrap(fn) { return new XWrap(fn); } function _arity(n, fn) { /* eslint-disable no-unused-vars */ switch (n) { case 0: return function() { return fn.apply(this, arguments); }; case 1: return function(a0) { return fn.apply(this, arguments); }; case 2: return function(a0, a1) { return fn.apply(this, arguments); }; case 3: return function(a0, a1, a2) { return fn.apply(this, arguments); }; case 4: return function(a0, a1, a2, a3) { return fn.apply(this, arguments); }; case 5: return function(a0, a1, a2, a3, a4) { return fn.apply(this, arguments); }; case 6: return function(a0, a1, a2, a3, a4, a5) { return fn.apply(this, arguments); }; case 7: return function(a0, a1, a2, a3, a4, a5, a6) { return fn.apply(this, arguments); }; case 8: return function(a0, a1, a2, a3, a4, a5, a6, a7) { return fn.apply(this, arguments); }; case 9: return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) { return fn.apply(this, arguments); }; case 10: return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { return fn.apply(this, arguments); }; default: throw new Error('First argument to _arity must be a non-negative integer no greater than ten'); } } /** * Creates a function that is bound to a context. * Note: `R.bind` does not provide the additional argument-binding capabilities of * [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). * * @func * @memberOf R * @since v0.6.0 * @category Function * @category Object * @sig (* -> *) -> {*} -> (* -> *) * @param {Function} fn The function to bind to context * @param {Object} thisObj The context to bind `fn` to * @return {Function} A function that will execute in the context of `thisObj`. * @see R.partial * @example * * const log = R.bind(console.log, console); * R.pipe(R.assoc('a', 2), R.tap(log), R.assoc('a', 3))({a: 1}); //=> {a: 3} * // logs {a: 2} * @symb R.bind(f, o)(a, b) = f.call(o, a, b) */ var bind = _curry2(function bind(fn, thisObj) { return _arity(fn.length, function() { return fn.apply(thisObj, arguments); }); }); function _arrayReduce(xf, acc, list) { var idx = 0; var len = list.length; while (idx < len) { acc = xf['@@transducer/step'](acc, list[idx]); if (acc && acc['@@transducer/reduced']) { acc = acc['@@transducer/value']; break; } idx += 1; } return xf['@@transducer/result'](acc); } function _iterableReduce(xf, acc, iter) { var step = iter.next(); while (!step.done) { acc = xf['@@transducer/step'](acc, step.value); if (acc && acc['@@transducer/reduced']) { acc = acc['@@transducer/value']; break; } step = iter.next(); } return xf['@@transducer/result'](acc); } function _methodReduce(xf, acc, obj, methodName) { return xf['@@transducer/result'](obj[methodName](bind(xf['@@transducer/step'], xf), acc)); } var symIterator = (typeof Symbol !== 'undefined') ? Symbol.iterator : '@@iterator'; function _reduce(fn, acc, list) { if (typeof fn === 'function') { fn = _xwrap(fn); } if (_isArrayLike(list)) { return _arrayReduce(fn, acc, list); } if (typeof list['fantasy-land/reduce'] === 'function') { return _methodReduce(fn, acc, list, 'fantasy-land/reduce'); } if (list[symIterator] != null) { return _iterableReduce(fn, acc, list[symIterator]()); } if (typeof list.next === 'function') { return _iterableReduce(fn, acc, list); } if (typeof list.reduce === 'function') { return _methodReduce(fn, acc, list, 'reduce'); } throw new TypeError('reduce: list must be array or iterable'); } /** * Returns a single item by iterating through the list, successively calling * the iterator function and passing it an accumulator value and the current * value from the array, and then passing the result to the next call. * * The iterator function receives two values: *(acc, value)*. It may use * [`R.reduced`](#reduced) to shortcut the iteration. * * The arguments' order of [`reduceRight`](#reduceRight)'s iterator function * is *(value, acc)*. * * Note: `R.reduce` does not skip deleted or unassigned indices (sparse * arrays), unlike the native `Array.prototype.reduce` method. For more details * on this behavior, see: * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description * * Dispatches to the `reduce` method of the third argument, if present. When * doing so, it is up to the user to handle the [`R.reduced`](#reduced) * shortcuting, as this is not implemented by `reduce`. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig ((a, b) -> a) -> a -> [b] -> a * @param {Function} fn The iterator function. Receives two values, the accumulator and the * current element from the array. * @param {*} acc The accumulator value. * @param {Array} list The list to iterate over. * @return {*} The final, accumulated value. * @see R.reduced, R.addIndex, R.reduceRight * @example * * R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10 * // - -10 * // / \ / \ * // - 4 -6 4 * // / \ / \ * // - 3 ==> -3 3 * // / \ / \ * // - 2 -1 2 * // / \ / \ * // 0 1 0 1 * * @symb R.reduce(f, a, [b, c, d]) = f(f(f(a, b), c), d) */ var reduce = _curry3(_reduce); exports.reduce = reduce; Object.defineProperty(exports, '__esModule', { value: true }); })));