This library uses some functions that come from the ramda Javascript utility library. I don't want to force a ramda dependency on other users of my library so I'm copying the used functions directly from their source.
/* eslint-disable */ ;(function() { 'use strict'; /* eslint-disable no-unused-vars */ var _arity = 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'); } }; var _arrayFromIterator = function _arrayFromIterator(iter) { var list = []; var next; while (!(next = iter.next()).done) { list.push(next.value); } return list; }; var _complement = function _complement(f) { return function () { return !f.apply(this, arguments); }; }; var _filter = 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; }; // String(x => x) evaluates to "x => x", so the pattern may not match. var _functionName = 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]; }; var _has = function _has(prop, obj) { return Object.prototype.hasOwnProperty.call(obj, prop); }; var _isArguments = function () { var toString = Object.prototype.toString; return toString.call(arguments) === '[object Arguments]' ? function _isArguments(x) { return toString.call(x) === '[object Arguments]'; } : function _isArguments(x) { return _has('callee', x); }; }(); /** * 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]'; }; var _isObject = function _isObject(x) { return Object.prototype.toString.call(x) === '[object Object]'; }; var _isPlaceholder = function _isPlaceholder(a) { return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true; }; var _isString = function _isString(x) { return Object.prototype.toString.call(x) === '[object String]'; }; var _isTransformer = function _isTransformer(obj) { return typeof obj['@@transducer/step'] === 'function'; }; var _map = 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; }; // \b matches word boundary; [\b] matches backspace var _quote = 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, '\\"') + '"'; }; /** * An optimized, private array `slice` implementation. * * @private * @param {Arguments|Array} args The array or arguments object to consider. * @param {Number} [from=0] The array index to slice from, inclusive. * @param {Number} [to=args.length] The array index to slice to, exclusive. * @return {Array} A new, sliced array. * @example * * _slice([1, 2, 3, 4, 5], 1, 3); //=> [2, 3] * * var firstThreeArgs = function(a, b, c, d) { * return _slice(arguments, 0, 3); * }; * firstThreeArgs(1, 2, 3, 4); //=> [1, 2, 3] */ var _slice = function _slice(args, from, to) { switch (arguments.length) { case 1: return _slice(args, 0, args.length); case 2: return _slice(args, from, args.length); default: var list = []; var idx = 0; var len = Math.max(0, Math.min(args.length, to) - from); while (idx < len) { list[idx] = args[from + idx]; idx += 1; } return list; } }; /** * Polyfill from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString>. */ var _toISOString = function () { var pad = function pad(n) { return (n < 10 ? '0' : '') + n; }; return 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'; }; }(); var _xfBase = { init: function () { return this.xf['@@transducer/init'](); }, result: function (result) { return this.xf['@@transducer/result'](result); } }; var _xwrap = function () { 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); }; return function _xwrap(fn) { return new XWrap(fn); }; }(); /** * Optimized internal one-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ var _curry1 = 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. */ var _curry2 = 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); } }; }; /** * 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 [methodname], it will execute that * function (functor case). Otherwise, if it is a transformer, uses transducer * [xf] to return a new transformer (transducer case). Otherwise, it will * default to executing [fn]. * * @private * @param {String} methodname property to check for a custom implementation * @param {Function} xf transducer to initialize if object is transformer * @param {Function} fn default ramda implementation * @return {Function} A function that dispatches on object in list position */ var _dispatchable = function _dispatchable(methodname, xf, fn) { return function () { var length = arguments.length; if (length === 0) { return fn(); } var obj = arguments[length - 1]; if (!_isArray(obj)) { var args = _slice(arguments, 0, length - 1); if (typeof obj[methodname] === 'function') { return obj[methodname].apply(obj, args); } if (_isTransformer(obj)) { var transducer = xf.apply(null, args); return transducer(obj); } } return fn.apply(this, arguments); }; }; var _xfilter = function () { 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; }; return _curry2(function _xfilter(f, xf) { return new XFilter(f, xf); }); }(); /** * 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 * * var 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} */ var bind = _curry2(function bind(fn, thisObj) { return _arity(fn.length, function () { return fn.apply(thisObj, arguments); }); }); /** * Returns true if its arguments are identical, false otherwise. Values are * identical if they reference the same memory. `NaN` is identical to `NaN`; * `0` and `-0` are not identical. * * @func * @memberOf R * @since v0.15.0 * @category Relation * @sig a -> a -> Boolean * @param {*} a * @param {*} b * @return {Boolean} * @example * * var o = {}; * R.identical(o, o); //=> true * R.identical(1, 1); //=> true * R.identical(1, '1'); //=> false * R.identical([], []); //=> false * R.identical(0, -0); //=> false * R.identical(NaN, NaN); //=> true */ // SameValue algorithm // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 // Step 6.a: NaN == NaN var identical = _curry2(function identical(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; } }); /** * Tests whether or not an object is similar to an array. * * @func * @memberOf R * @since v0.5.0 * @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 * * R.isArrayLike([]); //=> true * R.isArrayLike(true); //=> false * R.isArrayLike({}); //=> false * R.isArrayLike({length: 10}); //=> false * R.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; }); /** * 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. * @example * * R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c'] */ // cover IE < 9 keys issues // Safari bug var keys = function () { // 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 () { 'use strict'; 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; }; return 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" */ var type = _curry1(function type(val) { return val === null ? 'Null' : val === undefined ? 'Undefined' : Object.prototype.toString.call(val).slice(8, -1); }); /** * Returns a list of all the enumerable own properties of the supplied object. * Note that the order of the output array is not guaranteed across different * JS platforms. * * @func * @memberOf R * @since v0.1.0 * @category Object * @sig {k: v} -> [v] * @param {Object} obj The object to extract values from * @return {Array} An array of the values of the object's own properties. * @example * * R.values({a: 1, b: 2, c: 3}); //=> [1, 2, 3] */ var values = _curry1(function values(obj) { var props = keys(obj); var len = props.length; var vals = []; var idx = 0; while (idx < len) { vals[idx] = obj[props[idx]]; idx += 1; } return vals; }); // Values of other types are only equal if identical. var _equals = function _equals(a, b, stackA, stackB) { if (identical(a, b)) { return true; } if (type(a) !== type(b)) { return false; } if (a == null || b == null) { return false; } 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 (type(a)) { 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 && identical(a.valueOf(), b.valueOf()))) { return false; } break; case 'Date': if (!identical(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; case 'Map': case 'Set': if (!_equals(_arrayFromIterator(a.entries()), _arrayFromIterator(b.entries()), stackA, stackB)) { return false; } break; case 'Int8Array': case 'Uint8Array': case 'Uint8ClampedArray': case 'Int16Array': case 'Uint16Array': case 'Int32Array': case 'Uint32Array': case 'Float32Array': case 'Float64Array': break; 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 idx = stackA.length - 1; while (idx >= 0) { if (stackA[idx] === a) { return stackB[idx] === b; } idx -= 1; } stackA.push(a); stackB.push(b); idx = keysA.length - 1; while (idx >= 0) { var key = keysA[idx]; if (!(_has(key, b) && _equals(b[key], a[key], stackA, stackB))) { return false; } idx -= 1; } stackA.pop(); stackB.pop(); return true; }; var _reduce = function () { 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) { return xf['@@transducer/result'](obj.reduce(bind(xf['@@transducer/step'], xf), acc)); } var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator'; return function _reduce(fn, acc, list) { if (typeof fn === 'function') { fn = _xwrap(fn); } if (isArrayLike(list)) { return _arrayReduce(fn, acc, list); } if (typeof list.reduce === 'function') { return _methodReduce(fn, acc, list); } if (list[symIterator] != null) { return _iterableReduce(fn, acc, list[symIterator]()); } if (typeof list.next === 'function') { return _iterableReduce(fn, acc, list); } throw new TypeError('reduce: list must be array or iterable'); }; }(); /** * 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 * * var a = {}; a.v = a; * var b = {}; b.v = b; * R.equals(a, b); //=> true */ var equals = _curry2(function equals(a, b) { return _equals(a, b, [], []); }); /** * 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. * * 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 * @sig Filterable f => (a -> Boolean) -> f a -> f a * @param {Function} pred * @param {Array} filterable * @return {Array} * @see R.reject, R.transduce, R.addIndex * @example * * var 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} */ // else var filter = _curry2(_dispatchable('filter', _xfilter, function (pred, filterable) { return _isObject(filterable) ? _reduce(function (acc, key) { if (pred(filterable[key])) { acc[key] = filterable[key]; } return acc; }, {}, keys(filterable)) : // else _filter(pred, filterable); })); /** * An Object-specific version of `map`. The function is applied to three * arguments: *(value, key, obj)*. If only the value is significant, use * `map` instead. * * @func * @memberOf R * @since v0.9.0 * @category Object * @sig ((*, String, Object) -> *) -> Object -> Object * @param {Function} fn * @param {Object} obj * @return {Object} * @see R.map * @example * * var values = { x: 1, y: 2, z: 3 }; * var prependKeyAndDouble = (num, key, obj) => key + (num * 2); * * R.mapObjIndexed(prependKeyAndDouble, values); //=> { x: 'x2', y: 'y4', z: 'z6' } */ var mapObjIndexed = _curry2(function mapObjIndexed(fn, obj) { return _reduce(function (acc, key) { acc[key] = fn(obj[key], key, obj); return acc; }, {}, keys(obj)); }); /** * The complement of `filter`. * * Acts as a transducer if a transformer is given in list position. * * @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 * * var isOdd = (n) => n % 2 === 1; * * 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); }); // Array.prototype.indexOf doesn't exist below IE9 // manually crawl the list to distinguish between +0 and -0 // NaN // non-zero numbers can utilise Set // all these types can utilise Set // null can utilise Set // anything else not covered above, defer to R.equals var _indexOf = 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; }; var _contains = function _contains(a, list) { return _indexOf(list, a, 0) >= 0; }; // mapPairs :: (Object, [String]) -> [String] var _toString = function _toString(x, seen) { var recur = function recur(y) { var xs = seen.concat([x]); return _contains(y, xs) ? '<Circular>' : _toString(y, xs); }; // mapPairs :: (Object, [String]) -> [String] var mapPairs = function (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 Null]': return 'null'; case '[object Number]': return typeof x === 'object' ? 'new Number(' + recur(x.valueOf()) + ')' : 1 / x === -Infinity ? '-0' : x.toString(10); 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 = _curry1(function toString(val) { return _toString(val, []); }); /** * Creates a new function that, when invoked, caches the result of calling `fn` * for a given argument set and returns the result. Subsequent calls to the * memoized `fn` with the same argument set will not result in an additional * call to `fn`; instead, the cached result for that set of arguments will be * returned. * * @func * @memberOf R * @since v0.1.0 * @category Function * @sig (*... -> a) -> (*... -> a) * @param {Function} fn The function to memoize. * @return {Function} Memoized version of `fn`. * @example * * var count = 0; * var factorial = R.memoize(n => { * count += 1; * return R.product(R.range(1, n + 1)); * }); * factorial(5); //=> 120 * factorial(5); //=> 120 * factorial(5); //=> 120 * count; //=> 1 */ var memoize = _curry1(function memoize(fn) { var cache = {}; return _arity(fn.length, function () { var key = toString(arguments); if (!_has(key, cache)) { cache[key] = fn.apply(this, arguments); } return cache[key]; }); }); var R = { mapObjIndexed: mapObjIndexed, memoize: memoize, values: values }; /* eslint-env amd */ /* TEST_ENTRY_POINT */ if (typeof exports === 'object') { module.exports = R; } else if (typeof define === 'function' && define.amd) { define(function() { return R; }); } else { this.R = R; } }.call(this)); /* eslint-enable */