UNPKG

ramda

Version:

A practical functional library for JavaScript programmers.

1,611 lines (1,537 loc) 351 kB
// Ramda v0.31.3 // https://github.com/ramda/ramda // (c) 2013-2025 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) : (global = global || self, factory(global.R = {})); }(this, (function (exports) { 'use strict'; /** * A function that always returns `false`. Any passed in parameters are ignored. * * @func * @memberOf R * @since v0.9.0 * @category Function * @sig * -> Boolean * @param {*} * @return {Boolean} * @see R.T * @example * * R.F(); //=> false */ var F = function F() { return false; }; /** * A function that always returns `true`. Any passed in parameters are ignored. * * @func * @memberOf R * @since v0.9.0 * @category Function * @sig * -> Boolean * @param {*} * @return {Boolean} * @see R.F * @example * * R.T(); //=> true */ var T = function T() { return true; }; /** * A special placeholder value used to specify "gaps" within curried functions, * allowing partial application of any combination of arguments, regardless of * their positions. * * If `g` is a curried ternary function and `_` is `R.__`, the following are * equivalent: * * - `g(1, 2, 3)` * - `g(_, 2, 3)(1)` * - `g(_, _, 3)(1)(2)` * - `g(_, _, 3)(1, 2)` * - `g(_, 2, _)(1, 3)` * - `g(_, 2)(1)(3)` * - `g(_, 2)(1, 3)` * - `g(_, 2)(_, 3)(1)` * * @name __ * @constant * @memberOf R * @since v0.6.0 * @category Function * @example * * const greet = R.replace('{name}', R.__, 'Hello, {name}!'); * greet('Alice'); //=> 'Hello, Alice!' */ var __ = { '@@functional/placeholder': true }; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 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); } }; } /** * Adds two values. * * @func * @memberOf R * @since v0.1.0 * @category Math * @sig Number -> Number -> Number * @param {Number} a * @param {Number} b * @return {Number} * @see R.subtract * @example * * R.add(2, 3); //=> 5 * R.add(7)(10); //=> 17 */ var add = _curry2(function add(a, b) { return Number(a) + Number(b); }); /** * Private `concat` function to merge two array-like objects. * * @private * @param {Array|Arguments} [set1=[]] An array-like object. * @param {Array|Arguments} [set2=[]] An array-like object. * @return {Array} A new, merged array. * @example * * _concat([4, 5, 6], [1, 2, 3]); //=> [4, 5, 6, 1, 2, 3] */ function _concat(set1, set2) { set1 = set1 || []; set2 = set2 || []; var idx; var len1 = set1.length; var len2 = set2.length; var result = []; idx = 0; while (idx < len1) { result[result.length] = set1[idx]; idx += 1; } idx = 0; while (idx < len2) { result[result.length] = set2[idx]; idx += 1; } return result; } 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'); } } /** * Internal curryN function. * * @private * @category Function * @param {Number} length The arity of the curried function. * @param {Array} received An array of arguments received thus far. * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curryN(length, received, fn) { return function () { var combined = []; var argsIdx = 0; var left = length; var combinedIdx = 0; var hasPlaceholder = false; while (combinedIdx < received.length || argsIdx < arguments.length) { var result; if (combinedIdx < received.length && (!_isPlaceholder(received[combinedIdx]) || argsIdx >= arguments.length)) { result = received[combinedIdx]; } else { result = arguments[argsIdx]; argsIdx += 1; } combined[combinedIdx] = result; if (!_isPlaceholder(result)) { left -= 1; } else { hasPlaceholder = true; } combinedIdx += 1; } return !hasPlaceholder && left <= 0 ? fn.apply(this, combined) : _arity(Math.max(0, left), _curryN(length, combined, fn)); }; } /** * Returns a curried equivalent of the provided function, with the specified * arity. The curried function has two unusual capabilities. First, its * arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the * following are equivalent: * * - `g(1)(2)(3)` * - `g(1)(2, 3)` * - `g(1, 2)(3)` * - `g(1, 2, 3)` * * Secondly, the special placeholder value [`R.__`](#__) may be used to specify * "gaps", allowing partial application of any combination of arguments, * regardless of their positions. If `g` is as above and `_` is [`R.__`](#__), * the following are equivalent: * * - `g(1, 2, 3)` * - `g(_, 2, 3)(1)` * - `g(_, _, 3)(1)(2)` * - `g(_, _, 3)(1, 2)` * - `g(_, 2)(1)(3)` * - `g(_, 2)(1, 3)` * - `g(_, 2)(_, 3)(1)` * * @func * @memberOf R * @since v0.5.0 * @category Function * @sig Number -> (* -> a) -> (* -> a) * @param {Number} length The arity for the returned function. * @param {Function} fn The function to curry. * @return {Function} A new, curried function. * @see R.curry * @example * * const sumArgs = (...args) => R.sum(args); * * const curriedAddFourNumbers = R.curryN(4, sumArgs); * const f = curriedAddFourNumbers(1, 2); * const g = f(3); * g(4); //=> 10 */ var curryN = _curry2(function curryN(length, fn) { if (length === 1) { return _curry1(fn); } return _arity(length, _curryN(length, [], fn)); }); /** * Creates a new list iteration function from an existing one by adding two new * parameters to its callback function: the current index, and the entire list. * * This would turn, for instance, [`R.map`](#map) function into one that * more closely resembles `Array.prototype.map`. Note that this will only work * for functions in which the iteration callback function is the first * parameter, and where the list is the last parameter. (This latter might be * unimportant if the list parameter is not used.) * * @func * @memberOf R * @since v0.15.0 * @category Function * @category List * @sig (((a ...) -> b) ... -> [a] -> *) -> (((a ..., Int, [a]) -> b) ... -> [a] -> *) * @param {Function} fn A list iteration function that does not pass index or list to its callback * @return {Function} An altered list iteration function that passes (item, index, list) to its callback * @example * * const mapIndexed = R.addIndex(R.map); * mapIndexed((val, idx) => idx + '-' + val, ['f', 'o', 'o', 'b', 'a', 'r']); * //=> ['0-f', '1-o', '2-o', '3-b', '4-a', '5-r'] */ var addIndex = _curry1(function addIndex(fn) { return curryN(fn.length, function () { var idx = 0; var origFn = arguments[0]; var list = arguments[arguments.length - 1]; var args = Array.prototype.slice.call(arguments, 0); args[0] = function () { var result = origFn.apply(this, _concat(arguments, [idx, list])); idx += 1; return result; }; return fn.apply(this, args); }); }); /** * As with `addIndex`, `addIndexRight` creates a new list iteration function * from an existing one by adding two new parameters to its callback function: * the current index, and the entire list. * * Unlike `addIndex`, `addIndexRight` iterates from the right to the left. * * @func * @memberOf R * @since v0.29.0 * @category Function * @category List * @sig ((a ... -> b) ... -> [a] -> *) -> (a ..., Int, [a] -> b) ... -> [a] -> *) * @param {Function} fn A list iteration function that does not pass index or list to its callback * @return {Function} An altered list iteration function that passes (item, index, list) to its callback * @example * * const revmap = (fn, ary) => R.map(fn, R.reverse(ary)); * const revmapIndexed = R.addIndexRight(revmap); * revmapIndexed((val, idx) => idx + '-' + val, ['f', 'o', 'o', 'b', 'a', 'r']); * //=> [ '5-r', '4-a', '3-b', '2-o', '1-o', '0-f' ] */ var addIndexRight = _curry1(function addIndex(fn) { return curryN(fn.length, function () { var origFn = arguments[0]; var list = arguments[arguments.length - 1]; var idx = list.length - 1; var args = Array.prototype.slice.call(arguments, 0); args[0] = function () { var result = origFn.apply(this, _concat(arguments, [idx, list])); idx -= 1; return result; }; return fn.apply(this, args); }); }); /** * 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); } }; } /** * Applies a function to the value at the given index of an array, returning a * new copy of the array with the element at the given index replaced with the * result of the function application. * * When `idx < -list.length || idx >= list.length`, the original list is returned. * * @func * @memberOf R * @since v0.14.0 * @category List * @sig Number -> (a -> a) -> [a] -> [a] * @param {Number} idx The index. * @param {Function} fn The function to apply. * @param {Array|Arguments} list An array-like object whose value * at the supplied index will be replaced. * @return {Array} A copy of the supplied array-like object with * the element at index `idx` replaced with the value * returned by applying `fn` to the existing element. * @see R.update * @example * * R.adjust(1, R.toUpper, ['a', 'b', 'c', 'd']); //=> ['a', 'B', 'c', 'd'] * R.adjust(-1, R.toUpper, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c', 'D'] * * // out-of-range returns original list * R.adjust(4, R.toUpper, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c', 'd'] * R.adjust(-5, R.toUpper, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c', 'd'] * @symb R.adjust(-1, f, [a, b]) = [a, f(b)] * @symb R.adjust(0, f, [a, b]) = [f(a), b] */ var adjust = _curry3(function adjust(idx, fn, list) { var len = list.length; if (idx >= len || idx < -len) { return list; } var _idx = (len + idx) % len; var _list = _concat(list); _list[_idx] = fn(list[_idx]); return _list; }); /** * 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 _isTransformer(obj) { return obj != null && typeof obj['@@transducer/step'] === 'function'; } /** * Returns a function that dispatches with different strategies based on the * object in list position (last argument). If it is an array, executes [fn]. * Otherwise, if it has a function with one of the given method names, it will * execute that function (functor case). Otherwise, if it is a transformer, * uses transducer created by [transducerCreator] to return a new transformer * (transducer case). * Otherwise, it will default to executing [fn]. * * @private * @param {Array} methodNames properties to check for a custom implementation * @param {Function} transducerCreator transducer factory if object is transformer * @param {Function} fn default ramda implementation * @return {Function} A function that dispatches on object in list position */ function _dispatchable(methodNames, transducerCreator, fn) { return function () { if (arguments.length === 0) { return fn(); } var obj = arguments[arguments.length - 1]; if (!_isArray(obj)) { var idx = 0; while (idx < methodNames.length) { if (typeof obj[methodNames[idx]] === 'function') { return obj[methodNames[idx]].apply(obj, Array.prototype.slice.call(arguments, 0, -1)); } idx += 1; } if (_isTransformer(obj)) { var transducer = transducerCreator.apply(null, Array.prototype.slice.call(arguments, 0, -1)); return transducer(obj); } } return fn.apply(this, arguments); }; } function _reduced(x) { return x && x['@@transducer/reduced'] ? x : { '@@transducer/value': x, '@@transducer/reduced': true }; } var _xfBase = { init: function init() { return this.xf['@@transducer/init'](); }, result: function result(_result) { return this.xf['@@transducer/result'](_result); } }; function XAll(f, xf) { this.xf = xf; this.f = f; this.all = true; } XAll.prototype['@@transducer/init'] = _xfBase.init; XAll.prototype['@@transducer/result'] = function (result) { if (this.all) { result = this.xf['@@transducer/step'](result, true); } return this.xf['@@transducer/result'](result); }; XAll.prototype['@@transducer/step'] = function (result, input) { if (!this.f(input)) { this.all = false; result = _reduced(this.xf['@@transducer/step'](result, false)); } return result; }; function _xall(f) { return function (xf) { return new XAll(f, xf); }; } /** * Returns `true` if all elements of the list match the predicate, `false` if * there are any that don't. * * Dispatches to the `all` method of the second argument, if present. * * Acts as a transducer if a transformer is given in list position. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig (a -> Boolean) -> [a] -> Boolean * @param {Function} fn The predicate function. * @param {Array} list The array to consider. * @return {Boolean} `true` if the predicate is satisfied by every element, `false` * otherwise. * @see R.any, R.none, R.transduce * @example * * const equals3 = R.equals(3); * R.all(equals3)([3, 3, 3, 3]); //=> true * R.all(equals3)([3, 3, 1, 3]); //=> false */ var all = _curry2(_dispatchable(['all'], _xall, function all(fn, list) { var idx = 0; while (idx < list.length) { if (!fn(list[idx])) { return false; } idx += 1; } return true; })); function _arrayFromIterator(iter) { var list = []; var next; while (!(next = iter.next()).done) { list.push(next.value); } return list; } function _includesWith(pred, x, list) { var idx = 0; var len = list.length; while (idx < len) { if (pred(x, list[idx])) { return true; } idx += 1; } return false; } function _functionName(f) { // String(x => x) evaluates to "x => x", so the pattern may not match. var match = String(f).match(/^function (\w*)/); return match == null ? '' : match[1]; } function _has(prop, obj) { return Object.prototype.hasOwnProperty.call(obj, prop); } // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is function _objectIs(a, b) { // SameValue algorithm if (a === b) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return a !== 0 || 1 / a === 1 / b; } else { // Step 6.a: NaN == NaN return a !== a && b !== b; } } var _objectIs$1 = typeof Object.is === 'function' ? Object.is : _objectIs; var toString = Object.prototype.toString; var _isArguments = function () { return toString.call(arguments) === '[object Arguments]' ? function _isArguments(x) { return toString.call(x) === '[object Arguments]'; } : function _isArguments(x) { return _has('callee', x); }; }(); // cover IE < 9 keys issues var hasEnumBug = !{ toString: null }.propertyIsEnumerable('toString'); var nonEnumerableProps = ['constructor', 'valueOf', 'isPrototypeOf', 'toString', 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; // Safari bug var hasArgsEnumBug = function () { return arguments.propertyIsEnumerable('length'); }(); var contains = function contains(list, item) { var idx = 0; while (idx < list.length) { if (list[idx] === item) { return true; } idx += 1; } return false; }; /** * Returns a list containing the names of all the enumerable own properties of * the supplied object. * Note that the order of the output array is not guaranteed to be consistent * across different JS platforms. * * @func * @memberOf R * @since v0.1.0 * @category Object * @sig {k: v} -> [k] * @param {Object} obj The object to extract properties from * @return {Array} An array of the object's own properties. * @see R.keysIn, R.values, R.toPairs * @example * * R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c'] */ var keys = typeof Object.keys === 'function' && !hasArgsEnumBug ? _curry1(function keys(obj) { return Object(obj) !== obj ? [] : Object.keys(obj); }) : _curry1(function keys(obj) { if (Object(obj) !== obj) { return []; } var prop, nIdx; var ks = []; var checkArgsLength = hasArgsEnumBug && _isArguments(obj); for (prop in obj) { if (_has(prop, obj) && (!checkArgsLength || prop !== 'length')) { ks[ks.length] = prop; } } if (hasEnumBug) { nIdx = nonEnumerableProps.length - 1; while (nIdx >= 0) { prop = nonEnumerableProps[nIdx]; if (_has(prop, obj) && !contains(ks, prop)) { ks[ks.length] = prop; } nIdx -= 1; } } return ks; }); /** * Gives a single-word string description of the (native) type of a value, * returning such answers as 'Object', 'Number', 'Array', or 'Null'. Does not * attempt to distinguish user Object types any further, reporting them all as * 'Object'. * * @func * @memberOf R * @since v0.8.0 * @category Type * @sig * -> String * @param {*} val The value to test * @return {String} * @example * * R.type({}); //=> "Object" * R.type(1); //=> "Number" * R.type(false); //=> "Boolean" * R.type('s'); //=> "String" * R.type(null); //=> "Null" * R.type([]); //=> "Array" * R.type(/[A-z]/); //=> "RegExp" * R.type(() => {}); //=> "Function" * R.type(async () => {}); //=> "AsyncFunction" * R.type(undefined); //=> "Undefined" * R.type(BigInt(123)); //=> "BigInt" */ var type = _curry1(function type(val) { return val === null ? 'Null' : val === undefined ? 'Undefined' : Object.prototype.toString.call(val).slice(8, -1); }); /** * private _uniqContentEquals function. * That function is checking equality of 2 iterator contents with 2 assumptions * - iterators lengths are the same * - iterators values are unique * * false-positive result will be returned for comparison of, e.g. * - [1,2,3] and [1,2,3,4] * - [1,1,1] and [1,2,3] * */ function _uniqContentEquals(aIterator, bIterator, stackA, stackB) { var a = _arrayFromIterator(aIterator); var b = _arrayFromIterator(bIterator); function eq(_a, _b) { return _equals(_a, _b, stackA.slice(), stackB.slice()); } // if *a* array contains any element that is not included in *b* return !_includesWith(function (b, aItem) { return !_includesWith(eq, aItem, b); }, b, a); } function _equals(a, b, stackA, stackB) { if (_objectIs$1(a, b)) { return true; } var typeA = type(a); if (typeA !== type(b)) { return false; } if (typeof a['fantasy-land/equals'] === 'function' || typeof b['fantasy-land/equals'] === 'function') { return typeof a['fantasy-land/equals'] === 'function' && a['fantasy-land/equals'](b) && typeof b['fantasy-land/equals'] === 'function' && b['fantasy-land/equals'](a); } if (typeof a.equals === 'function' || typeof b.equals === 'function') { return typeof a.equals === 'function' && a.equals(b) && typeof b.equals === 'function' && b.equals(a); } switch (typeA) { case 'Arguments': case 'Array': case 'Object': if (typeof a.constructor === 'function' && _functionName(a.constructor) === 'Promise') { return a === b; } break; case 'Boolean': case 'Number': case 'String': if (!(_typeof(a) === _typeof(b) && _objectIs$1(a.valueOf(), b.valueOf()))) { return false; } break; case 'Date': if (!_objectIs$1(a.valueOf(), b.valueOf())) { return false; } break; case 'Error': return a.name === b.name && a.message === b.message; case 'RegExp': if (!(a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.sticky === b.sticky && a.unicode === b.unicode)) { return false; } break; } var idx = stackA.length - 1; while (idx >= 0) { if (stackA[idx] === a) { return stackB[idx] === b; } idx -= 1; } switch (typeA) { case 'Map': if (a.size !== b.size) { return false; } return _uniqContentEquals(a.entries(), b.entries(), stackA.concat([a]), stackB.concat([b])); case 'Set': if (a.size !== b.size) { return false; } return _uniqContentEquals(a.values(), b.values(), stackA.concat([a]), stackB.concat([b])); case 'Arguments': case 'Array': case 'Object': case 'Boolean': case 'Number': case 'String': case 'Date': case 'Error': case 'RegExp': case 'Int8Array': case 'Uint8Array': case 'Uint8ClampedArray': case 'Int16Array': case 'Uint16Array': case 'Int32Array': case 'Uint32Array': case 'Float32Array': case 'Float64Array': case 'ArrayBuffer': break; default: // Values of other types are only equal if identical. return false; } var keysA = keys(a); if (keysA.length !== keys(b).length) { return false; } var extendedStackA = stackA.concat([a]); var extendedStackB = stackB.concat([b]); idx = keysA.length - 1; while (idx >= 0) { var key = keysA[idx]; if (!(_has(key, b) && _equals(b[key], a[key], extendedStackA, extendedStackB))) { return false; } idx -= 1; } return true; } /** * Returns `true` if its arguments are equivalent, `false` otherwise. Handles * cyclical data structures. * * Dispatches symmetrically to the `equals` methods of both arguments, if * present. * * @func * @memberOf R * @since v0.15.0 * @category Relation * @sig a -> b -> Boolean * @param {*} a * @param {*} b * @return {Boolean} * @example * * R.equals(1, 1); //=> true * R.equals(1, '1'); //=> false * R.equals([1, 2, 3], [1, 2, 3]); //=> true * * const a = {}; a.v = a; * const b = {}; b.v = b; * R.equals(a, b); //=> true */ var equals = _curry2(function equals(a, b) { return _equals(a, b, [], []); }); function _indexOf(list, a, idx) { var inf, item; // Array.prototype.indexOf doesn't exist below IE9 if (typeof list.indexOf === 'function') { switch (_typeof(a)) { case 'number': if (a === 0) { // manually crawl the list to distinguish between +0 and -0 inf = 1 / a; while (idx < list.length) { item = list[idx]; if (item === 0 && 1 / item === inf) { return idx; } idx += 1; } return -1; } else if (a !== a) { // NaN while (idx < list.length) { item = list[idx]; if (typeof item === 'number' && item !== item) { return idx; } idx += 1; } return -1; } // non-zero numbers can utilise Set return list.indexOf(a, idx); // all these types can utilise Set case 'string': case 'boolean': case 'function': case 'undefined': return list.indexOf(a, idx); case 'object': if (a === null) { // null can utilise Set return list.indexOf(a, idx); } } } // anything else not covered above, defer to R.equals while (idx < list.length) { if (equals(list[idx], a)) { return idx; } idx += 1; } return -1; } function _includes(a, list) { return _indexOf(list, a, 0) >= 0; } function _map(fn, functor) { var idx = 0; var len = functor.length; var result = Array(len); while (idx < len) { result[idx] = fn(functor[idx]); idx += 1; } return result; } function _quote(s) { var escaped = s.replace(/\\/g, '\\\\').replace(/[\b]/g, '\\b') // \b matches word boundary; [\b] matches backspace .replace(/\f/g, '\\f').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t').replace(/\v/g, '\\v').replace(/\0/g, '\\0'); return '"' + escaped.replace(/"/g, '\\"') + '"'; } /** * Polyfill from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString>. */ var pad = function pad(n) { return (n < 10 ? '0' : '') + n; }; var _toISOString = typeof Date.prototype.toISOString === 'function' ? function _toISOString(d) { return d.toISOString(); } : function _toISOString(d) { return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + '.' + (d.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) + 'Z'; }; function _complement(f) { return function () { return !f.apply(this, arguments); }; } function _arrayReduce(reducer, acc, list) { var index = 0; var length = list.length; while (index < length) { acc = reducer(acc, list[index]); index += 1; } return acc; } function _filter(fn, list) { var idx = 0; var len = list.length; var result = []; while (idx < len) { if (fn(list[idx])) { result[result.length] = list[idx]; } idx += 1; } return result; } function _filterMap(fn, map) { var result = new Map(); var iterator = map.entries(); var current = iterator.next(); while (!current.done) { if (fn(current.value[1])) { result.set(current.value[0], current.value[1]); } current = iterator.next(); } return result; } function _isMap(x) { return Object.prototype.toString.call(x) === '[object Map]'; } function _isObject(x) { return Object.prototype.toString.call(x) === '[object Object]'; } function XFilter(f, xf) { this.xf = xf; this.f = f; } XFilter.prototype['@@transducer/init'] = _xfBase.init; XFilter.prototype['@@transducer/result'] = _xfBase.result; XFilter.prototype['@@transducer/step'] = function (result, input) { return this.f(input) ? this.xf['@@transducer/step'](result, input) : result; }; function _xfilter(f) { return function (xf) { return new XFilter(f, xf); }; } /** * Takes a predicate and a `Filterable`, and returns a new filterable of the * same type containing the members of the given filterable which satisfy the * given predicate. Filterable objects include plain objects, Maps, or any object * that has a filter method such as `Array`. * * Dispatches to the `filter` method of the second argument, if present. * * Acts as a transducer if a transformer is given in list position. * * @func * @memberOf R * @since v0.1.0 * @category List * @category Object * @sig Filterable f => (a -> Boolean) -> f a -> f a * @param {Function} pred * @param {Array} filterable * @return {Array} Filterable * @see R.reject, R.transduce, R.addIndex * @example * * const isEven = n => n % 2 === 0; * * R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4] * * R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4} */ var filter = _curry2(_dispatchable(['fantasy-land/filter', 'filter'], _xfilter, function (pred, filterable) { return _isObject(filterable) ? _arrayReduce(function (acc, key) { if (pred(filterable[key])) { acc[key] = filterable[key]; } return acc; }, {}, keys(filterable)) : _isMap(filterable) ? _filterMap(pred, filterable) : // else _filter(pred, filterable); })); /** * The complement of [`filter`](#filter). * * Acts as a transducer if a transformer is given in list position. Filterable * objects include plain objects or any object that has a filter method such * as `Array`. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig Filterable f => (a -> Boolean) -> f a -> f a * @param {Function} pred * @param {Array} filterable * @return {Array} * @see R.filter, R.transduce, R.addIndex * @example * * const isOdd = (n) => n % 2 !== 0; * * R.reject(isOdd, [1, 2, 3, 4]); //=> [2, 4] * * R.reject(isOdd, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4} */ var reject = _curry2(function reject(pred, filterable) { return filter(_complement(pred), filterable); }); function _toString(x, seen) { var recur = function recur(y) { var xs = seen.concat([x]); return _includes(y, xs) ? '<Circular>' : _toString(y, xs); }; // mapPairs :: (Object, [String]) -> [String] var mapPairs = function mapPairs(obj, keys) { return _map(function (k) { return _quote(k) + ': ' + recur(obj[k]); }, keys.slice().sort()); }; switch (Object.prototype.toString.call(x)) { case '[object Arguments]': return '(function() { return arguments; }(' + _map(recur, x).join(', ') + '))'; case '[object Array]': return '[' + _map(recur, x).concat(mapPairs(x, reject(function (k) { return /^\d+$/.test(k); }, keys(x)))).join(', ') + ']'; case '[object Boolean]': return _typeof(x) === 'object' ? 'new Boolean(' + recur(x.valueOf()) + ')' : x.toString(); case '[object Date]': return 'new Date(' + (isNaN(x.valueOf()) ? recur(NaN) : _quote(_toISOString(x))) + ')'; case '[object Map]': return 'new Map(' + recur(Array.from(x)) + ')'; case '[object Null]': return 'null'; case '[object Number]': return _typeof(x) === 'object' ? 'new Number(' + recur(x.valueOf()) + ')' : 1 / x === -Infinity ? '-0' : x.toString(10); case '[object Set]': return 'new Set(' + recur(Array.from(x).sort()) + ')'; case '[object String]': return _typeof(x) === 'object' ? 'new String(' + recur(x.valueOf()) + ')' : _quote(x); case '[object Undefined]': return 'undefined'; default: if (typeof x.toString === 'function') { var repr = x.toString(); if (repr !== '[object Object]') { return repr; } } return '{' + mapPairs(x, keys(x)).join(', ') + '}'; } } /** * Returns the string representation of the given value. `eval`'ing the output * should result in a value equivalent to the input value. Many of the built-in * `toString` methods do not satisfy this requirement. * * If the given value is an `[object Object]` with a `toString` method other * than `Object.prototype.toString`, this method is invoked with no arguments * to produce the return value. This means user-defined constructor functions * can provide a suitable `toString` method. For example: * * function Point(x, y) { * this.x = x; * this.y = y; * } * * Point.prototype.toString = function() { * return 'new Point(' + this.x + ', ' + this.y + ')'; * }; * * R.toString(new Point(1, 2)); //=> 'new Point(1, 2)' * * @func * @memberOf R * @since v0.14.0 * @category String * @sig * -> String * @param {*} val * @return {String} * @example * * R.toString(42); //=> '42' * R.toString('abc'); //=> '"abc"' * R.toString([1, 2, 3]); //=> '[1, 2, 3]' * R.toString({foo: 1, bar: 2, baz: 3}); //=> '{"bar": 2, "baz": 3, "foo": 1}' * R.toString(new Date('2001-02-03T04:05:06Z')); //=> 'new Date("2001-02-03T04:05:06.000Z")' */ var toString$1 = _curry1(function toString(val) { return _toString(val, []); }); /** * Returns the larger of its two arguments. * * @func * @memberOf R * @since v0.1.0 * @category Relation * @sig Ord a => a -> a -> a * @param {*} a * @param {*} b * @return {*} * @see R.maxBy, R.min * @example * * R.max(789, 123); //=> 789 * R.max('a', 'b'); //=> 'b' */ var max = _curry2(function max(a, b) { if (a === b) { return b; } function safeMax(x, y) { if (x > y !== y > x) { return y > x ? y : x; } return undefined; } var maxByValue = safeMax(a, b); if (maxByValue !== undefined) { return maxByValue; } var maxByType = safeMax(_typeof(a), _typeof(b)); if (maxByType !== undefined) { return maxByType === _typeof(a) ? a : b; } var stringA = toString$1(a); var maxByStringValue = safeMax(stringA, toString$1(b)); if (maxByStringValue !== undefined) { return maxByStringValue === stringA ? a : b; } return b; }); function XMap(f, xf) { this.xf = xf; this.f = f; } XMap.prototype['@@transducer/init'] = _xfBase.init; XMap.prototype['@@transducer/result'] = _xfBase.result; XMap.prototype['@@transducer/step'] = function (result, input) { return this.xf['@@transducer/step'](result, this.f(input)); }; var _xmap = function _xmap(f) { return function (xf) { return new XMap(f, xf); }; }; /** * Takes a function and * a [functor](https://github.com/fantasyland/fantasy-land#functor), * applies the function to each of the functor's values, and returns * a functor of the same shape. * * Ramda provides suitable `map` implementations for `Array` and `Object`, * so this function may be applied to `[1, 2, 3]` or `{x: 1, y: 2, z: 3}`. * * Dispatches to the `map` method of the second argument, if present. * * Acts as a transducer if a transformer is given in list position. * * Also treats functions as functors and will compose them together. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig Functor f => (a -> b) -> f a -> f b * @param {Function} fn The function to be called on every element of the input `list`. * @param {Array} list The list to be iterated over. * @return {Array} The new list. * @see R.transduce, R.addIndex, R.pluck, R.project * @example * * const double = x => x * 2; * * R.map(double, [1, 2, 3]); //=> [2, 4, 6] * * R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6} * @symb R.map(f, [a, b]) = [f(a), f(b)] * @symb R.map(f, { x: a, y: b }) = { x: f(a), y: f(b) } * @symb R.map(f, functor_o) = functor_o.map(f) */ var map = _curry2(_dispatchable(['fantasy-land/map', 'map'], _xmap, function map(fn, functor) { switch (Object.prototype.toString.call(functor)) { case '[object Function]': return curryN(functor.length, function () { return fn.call(this, functor.apply(this, arguments)); }); case '[object Object]': return _arrayReduce(function (acc, key) { acc[key] = fn(functor[key]); return acc; }, {}, keys(functor)); default: return _map(fn, functor); } })); /** * Determine if the passed argument is an integer. * * @private * @param {*} n * @category Type * @return {Boolean} */ var _isInteger = Number.isInteger || function _isInteger(n) { return n << 0 === n; }; function _nth(offset, list) { var idx = offset < 0 ? list.length + offset : offset; return list[idx]; } function _prop(p, obj) { if (obj == null) { return; } return _isInteger(p) ? _nth(p, obj) : obj[p]; } /** * Returns a function that when supplied an object returns the indicated * property of that object, if it exists. * * @func * @memberOf R * @since v0.1.0 * @category Object * @typedefn Idx = String | Int | Symbol * @sig Idx -> {s: a} -> a | Undefined * @param {String|Number} p The property name or array index * @param {Object} obj The object to query * @return {*} The value at `obj.p`. * @see R.path, R.props, R.pluck, R.project, R.nth * @example * * R.prop('x', {x: 100}); //=> 100 * R.prop('x', {}); //=> undefined * R.prop(0, [100]); //=> 100 * R.compose(R.inc, R.prop('x'))({ x: 3 }) //=> 4 */ var prop = _curry2(_prop); /** * Returns a new list by plucking the same named property off all objects in * the list supplied. * * `pluck` will work on * any [functor](https://github.com/fantasyland/fantasy-land#functor) in * addition to arrays, as it is equivalent to `R.map(R.prop(k), f)`. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig Functor f => k -> f {k: v} -> f v * @param {Number|String} key The key name to pluck off of each object. * @param {Array} f The array or functor to consider. * @return {Array} The list of values for the given key. * @see R.project, R.prop, R.props * @example * * var getAges = R.pluck('age'); * getAges([{name: 'fred', age: 29}, {name: 'wilma', age: 27}]); //=> [29, 27] * * R.pluck(0, [[1, 2], [3, 4]]); //=> [1, 3] * R.pluck('val', {a: {val: 3}, b: {val: 5}}); //=> {a: 3, b: 5} * @symb R.pluck('x', [{x: 1, y: 2}, {x: 3, y: 4}, {x: 5, y: 6}]) = [1, 3, 5] * @symb R.pluck(0, [[1, 2], [3, 4], [5, 6]]) = [1, 3, 5] */ var pluck = _curry2(function pluck(p, list) { return map(prop(p), list); }); 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 * _isArrayLike({nodeType: 1, length: 1}) // => false */ 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.length === 0) { return true; } if (x.length > 0) { return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1); } return false; }); var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator'; function _createReduce(arrayReduce, methodReduce, iterableReduce) { return function _reduce(xf, acc, list) { if (_isArrayLike(list)) { return arrayReduce(xf, acc, list); } if (list == null) { return acc; } if (typeof list['fantasy-land/reduce'] === 'function') { return methodReduce(xf, acc, list, 'fantasy-land/reduce'); } if (list[symIterator] != null) { return iterableReduce(xf, acc, list[symIterator]()); } if (typeof list.next === 'function') { return iterableReduce(xf, acc, list); } if (typeof list.reduce === 'function') { return methodReduce(xf, acc, list, 'reduce'); } throw new TypeError('reduce: list must be array or iterable'); }; } function _xArrayReduce(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); } /** * 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 _xIterableReduce(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 _xMethodReduce(xf, acc, obj, methodName) { return xf['@@transducer/result'](obj[methodName](bind(xf['@@transducer/step'], xf), acc)); } var _xReduce = _createReduce(_xArrayReduce, _xMethodReduce, _xIterableReduce); 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); } /** * 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 * * Be cautious of mutating and returning the accumulator. If you reuse it across * invocations, it will continue to accumulate onto the same value. The general * recommendation is to always return a new value. If you can't do so for * performance reasons, then be sure to reinitialize the accumulator on each * invocation. * * 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 * //