diff --git a/dist/lamb.js b/dist/lamb.js index 7de6e49..b53dd08 100644 --- a/dist/lamb.js +++ b/dist/lamb.js @@ -1,7 +1,7 @@ /** * @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming. * @author Andrea Scartabelli - * @version 0.35.0 + * @version 0.36.0-alpha.3 * @module lamb * @license MIT * @preserve @@ -18,7 +18,7 @@ * @category Core * @type String */ - lamb._version = "0.35.0"; + lamb._version = "0.36.0-alpha.3"; // alias used as a placeholder argument for partial application var _ = lamb; diff --git a/dist/lamb.min.js b/dist/lamb.min.js index d4099fd..d9fc366 100644 --- a/dist/lamb.min.js +++ b/dist/lamb.min.js @@ -1,10 +1,10 @@ /** * @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming. * @author Andrea Scartabelli - * @version 0.35.0 + * @version 0.36.0-alpha.3 * @module lamb * @license MIT * @preserve */ -!function(n){"use strict";function t(n){return function(){return n}}function r(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}}function e(n){return n}function u(n){var t=_t(arguments,1);return function(){for(var r,e=0,u=[],i=t.length,o=0;ot||n!==n?r=1:(n=t?n.apply(this,r?i.reverse():i):c(n,t,r,e,i)}}function f(n,t,r,e){var u=e?function(n){var t=n.length;if(t){for(var r=0,e=[];r>>0!==t&&(t=n.length),t>1?c(n,t,r,u,[]):n}function a(n,t){return R(n,function(n){Array.isArray(n)?a(n,t):t.push(n)}),t}function l(n,t,r,e,u){if(0===n.length)return 0;var i=e+u>>1,o=r({value:t,index:i},{value:n[i],index:i});return u-e<=1?o<0?i:i+1:o<0?l(n,t,r,e,i):0===o?i+1:l(n,t,r,i,u)}function h(n,t){var r=n.length;if(O(t)&&O(r))return _(t,-r,r-1)===t?t<0?t+r:t:void 0}function p(n,t,r){var e=-1,u=n.length;for(3===arguments.length&&(t=t.bind(r));++e>>0,c=1===n?0:o-1;if(3===arguments.length)u=o,i=e;else{if(0===o)throw new TypeError("Reduce of empty array-like with no initial value");i=t[c],c+=n,u=o-1}for(;u--;c+=n)i=r(i,t[c],c,t);return i}}function x(n,t){return new TypeError("Cannot convert "+fn(n).toLowerCase()+" to "+t)}function I(n){return qt(_t(arguments,1),function(t,r){return R(n(r),function(n){t[n]=r[n]}),t},{})}function W(n){return function(t,r){var e=2===arguments.length?n:Xn(n);return u(e,Tt,t,r)}}function M(n){var t=[];for(var r in n)t.push(r);return t}function K(n,t,r,e){var u=_t(n),i=h(u,t),o=4===arguments.length;return cn(i)||(u[i]=o?e(n[i]):r),u}function P(n,t,r){var e=t[0],u=1===t.length?r:P(v(n,[e],!1).target,_t(t,1),r);return b(n,e)?K(n,+e,u):dn(Object(n),e,u)}function T(n,t,r){return{isDescending:t===!0,compare:function(t,u){return"function"==typeof n&&n!==e&&(t=n(t),u=n(u)),("function"==typeof r?r:i)(t,u)}}}function N(n,t){return String(n).split(t||".")}function E(n,t,r){var e=n.length,u=[];3===arguments.length&&(t=t.bind(r));for(var i=0;i>>0;e>>0,u=Array(e);3===arguments.length&&(t=t.bind(r));for(var i=0;it}function C(n,t){return n>=t}function G(n,t){return nr?r:n}function H(n,t){return n/t}function J(n,t,r,e){var u=[n];4===arguments.length&&(r=r.bind(e));for(var i=0,o=t-1;i>>0,i=n.length;u>>0,u=n.length,i=0;i0&&e=t&&(e=u,r=n.apply(this,arguments)),r}}function pt(n){return function(t){return n.call(this,t)}}function st(n,t,r,e){return function(i){var o=u(vn,i,Tt,e);return n.apply(i,S(r,o))?[]:[t,r]}}function vt(n){var t={};return R(n,function(n){t[n[0]]=n[1]}),t}function gt(n,t){return"object"==typeof n||cn(n)||(n=Object(n)),t in n}function dt(n){return function(t){return gt(t,n)}}function yt(n){return function(t){return Ar(t,n)}}function bt(n){return d(n,[])}function mt(n,t){for(var r={},e=t.length,u=0,i=n.length;ut||n!==n?r=1:(n=t?n.apply(this,r?i.reverse():i):c(n,t,r,e,i)}}function f(n,t,r,e){var u=e?function(n){var t=n.length;if(t){for(var r=0,e=[];r>>0!==t&&(t=n.length),t>1?c(n,t,r,u,[]):n}function a(n,t){return R(n,function(n){Array.isArray(n)?a(n,t):t.push(n)}),t}function l(n,t,r,e,u){if(0===n.length)return 0;var i=e+u>>1,o=r({value:t,index:i},{value:n[i],index:i});return u-e<=1?o<0?i:i+1:o<0?l(n,t,r,e,i):0===o?i+1:l(n,t,r,i,u)}function h(n,t){var r=n.length;if(O(t)&&O(r))return _(t,-r,r-1)===t?t<0?t+r:t:void 0}function p(n,t,r){var e=-1,u=n.length;for(3===arguments.length&&(t=t.bind(r));++e>>0,c=1===n?0:o-1;if(3===arguments.length)u=o,i=e;else{if(0===o)throw new TypeError("Reduce of empty array-like with no initial value");i=t[c],c+=n,u=o-1}for(;u--;c+=n)i=r(i,t[c],c,t);return i}}function x(n,t){return new TypeError("Cannot convert "+fn(n).toLowerCase()+" to "+t)}function I(n){return qt(_t(arguments,1),function(t,r){return R(n(r),function(n){t[n]=r[n]}),t},{})}function W(n){return function(t,r){var e=2===arguments.length?n:Xn(n);return u(e,Tt,t,r)}}function M(n){var t=[];for(var r in n)t.push(r);return t}function K(n,t,r,e){var u=_t(n),i=h(u,t),o=4===arguments.length;return cn(i)||(u[i]=o?e(n[i]):r),u}function P(n,t,r){var e=t[0],u=1===t.length?r:P(v(n,[e],!1).target,_t(t,1),r);return b(n,e)?K(n,+e,u):dn(Object(n),e,u)}function T(n,t,r){return{isDescending:t===!0,compare:function(t,u){return"function"==typeof n&&n!==e&&(t=n(t),u=n(u)),("function"==typeof r?r:i)(t,u)}}}function N(n,t){return String(n).split(t||".")}function E(n,t,r){var e=n.length,u=[];3===arguments.length&&(t=t.bind(r));for(var i=0;i>>0;e>>0,u=Array(e);3===arguments.length&&(t=t.bind(r));for(var i=0;it}function C(n,t){return n>=t}function G(n,t){return nr?r:n}function H(n,t){return n/t}function J(n,t,r,e){var u=[n];4===arguments.length&&(r=r.bind(e));for(var i=0,o=t-1;i>>0,i=n.length;u>>0,u=n.length,i=0;i0&&e=t&&(e=u,r=n.apply(this,arguments)),r}}function pt(n){return function(t){return n.call(this,t)}}function st(n,t,r,e){return function(i){var o=u(vn,i,Tt,e);return n.apply(i,S(r,o))?[]:[t,r]}}function vt(n){var t={};return R(n,function(n){t[n[0]]=n[1]}),t}function gt(n,t){return"object"==typeof n||cn(n)||(n=Object(n)),t in n}function dt(n){return function(t){return gt(t,n)}}function yt(n){return function(t){return Ar(t,n)}}function bt(n){return d(n,[])}function mt(n,t){for(var r={},e=t.length,u=0,i=n.length;u\n * @version 0.35.0\n * @module lamb\n * @license MIT\n * @preserve\n */\n!function (host) {\n \"use strict\";\n\n var lamb = Object.create(null);\n\n /**\n * The current module version.\n * @memberof module:lamb\n * @private\n * @category Core\n * @type String\n */\n lamb._version = \"0.35.0\";\n\n // alias used as a placeholder argument for partial application\n var _ = lamb;\n\n // some prototype shortcuts for internal use\n var _arrayProto = Array.prototype;\n var _objectProto = Object.prototype;\n var _reProto = RegExp.prototype;\n\n /**\n * Builds a function that returns a constant value.\n * It's actually the simplest form of the K combinator or Kestrel.\n * @example\n * var truth = _.always(true);\n *\n * truth() // => true\n * truth(false) // => true\n * truth(1, 2) // => true\n *\n * // the value being returned is actually the\n * // very same value passed to the function\n * var foo = {bar: \"baz\"};\n * var alwaysFoo = _.always(foo);\n *\n * alwaysFoo() === foo // => true\n *\n * @memberof module:lamb\n * @category Core\n * @see [SKI combinator calculus]{@link https://en.wikipedia.org/wiki/SKI_combinator_calculus}\n * @param {*} value\n * @returns {Function}\n */\n function always (value) {\n return function () {\n return value;\n };\n }\n\n /**\n * Returns a function that is the composition of the functions given as parameters.\n * Each function consumes the result of the function that follows.\n * @example\n * var sayHi = function (name) { return \"Hi, \" + name; };\n * var capitalize = function (s) {\n * return s[0].toUpperCase() + s.substr(1).toLowerCase();\n * };\n * var fixNameAndSayHi = _.compose(sayHi, capitalize);\n *\n * sayHi(\"bOb\") // => \"Hi, bOb\"\n * fixNameAndSayHi(\"bOb\") // \"Hi, Bob\"\n *\n * var getName = _.getKey(\"name\");\n * var users = [{name: \"fred\"}, {name: \"bOb\"}];\n * var sayHiToUser = _.compose(fixNameAndSayHi, getName);\n *\n * users.map(sayHiToUser) // [\"Hi, Fred\", \"Hi, Bob\"]\n *\n * @memberof module:lamb\n * @category Function\n * @param {...Function} fn\n * @returns {Function}\n */\n function compose () {\n var functions = arguments;\n\n return function () {\n var args = arguments;\n var len = functions.length;\n\n while (len--) {\n args = [functions[len].apply(this, args)];\n }\n\n return args[0];\n };\n }\n\n /**\n * Creates generic functions out of methods.\n * @memberof module:lamb\n * @category Core\n * @author A very little change on a great idea by [Irakli Gozalishvili]{@link https://github.com/Gozala/}. Thanks for this *beautiful* one-liner (never liked your \"unbind\" naming choice, though).\n * @function\n * @example\n * // Lamb's \"slice\" is actually implemented like this\n * var slice = _.generic(Array.prototype.slice);\n *\n * slice([\"foo\", \"bar\", \"baz\"], 0, -1) // => [\"foo\", \"bar\"]\n *\n * // the function will work with any array-like object\n * slice(\"fooBAR\", 0, 3) // => [\"f\", \"o\", \"o\"]\n *\n * @param {Function} method\n * @returns {Function}\n */\n var generic = Function.bind.bind(Function.call);\n\n /**\n * The I combinator. Any value passed to the function is simply returned as it is.\n * @example\n * var foo = {bar: \"baz\"};\n *\n * _.identity(foo) === foo // true\n *\n * @memberof module:lamb\n * @category Core\n * @see [SKI combinator calculus]{@link https://en.wikipedia.org/wiki/SKI_combinator_calculus}\n * @param {*} value\n * @returns {*} The value passed as parameter.\n */\n function identity (value) {\n return value;\n }\n\n /**\n * Builds a partially applied function. The lamb object itself can be used as a placeholder argument:\n * it's useful to alias it as _ or __.\n * @example\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n * var parseInt10 = _.partial(parseInt, _, 10);\n *\n * weights.map(parseInt10) // => [2, 10, 1, 7]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {...*} args\n * @returns {Function}\n */\n function partial (fn) {\n var args = slice(arguments, 1);\n\n return function () {\n var lastArgumentIdx = 0;\n var newArgs = [];\n var argsLen = args.length;\n\n for (var i = 0, boundArg; i < argsLen; i++) {\n boundArg = args[i];\n newArgs[i] = boundArg === _ ? arguments[lastArgumentIdx++] : boundArg;\n }\n\n for (var len = arguments.length; lastArgumentIdx < len; lastArgumentIdx++) {\n newArgs[i++] = arguments[lastArgumentIdx];\n }\n\n return fn.apply(this, newArgs);\n };\n }\n\n lamb.always = always;\n lamb.compose = compose;\n lamb.generic = generic;\n lamb.identity = identity;\n lamb.partial = partial;\n\n\n /**\n * The default comparer for sorting functions.
\n * If the given values are of different types they\n * will be both converted to strings.
\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\n function _comparer (a, b) {\n var result = 0;\n\n if (typeof a !== typeof b) {\n a = String(a);\n b = String(b);\n }\n\n if (!isSVZ(a, b)) {\n if (a > b || a !== a) {\n result = 1;\n } else if (a < b || b !== b) {\n result = -1;\n }\n }\n\n return result;\n }\n\n /**\n * Accepts a list of sorting criteria and builds a function that compares\n * two values with such criteria.\n * @private\n * @param {Sorter[]} criteria\n * @returns {Function}\n */\n function _compareWith (criteria) {\n var len = criteria.length;\n\n return function (a, b) {\n var result = 0;\n var isDescSort;\n var criterion;\n\n for (var i = 0; i < len; i++) {\n criterion = criteria[i];\n result = criterion.compare(a.value, b.value);\n\n if (result !== 0) {\n isDescSort = criteria[i].isDescending;\n break;\n }\n }\n\n if (result === 0) {\n isDescSort = criteria[len - 1].isDescending;\n result = a.index - b.index;\n }\n\n return isDescSort ? -result : result;\n };\n }\n\n /**\n * Used by curry functions to collect arguments until the arity is consumed,\n * then applies the original function.\n * @private\n * @param {Function} fn\n * @param {Number} arity\n * @param {Boolean} isRightCurry\n * @param {Function} slicer\n * @param {Array} argsHolder\n */\n function _currier (fn, arity, isRightCurry, slicer, argsHolder) {\n return function () {\n var args = argsHolder.concat(slicer(arguments));\n\n if (args.length >= arity) {\n return fn.apply(this, isRightCurry ? args.reverse() : args);\n } else {\n return _currier(fn, arity, isRightCurry, slicer, args);\n }\n };\n }\n\n /**\n * Prepares a function for currying by setting the proper parameters for\n * the _currier function.\n * If the desumed arity isn't greater than one, it will return the received\n * function itself, instead.\n * @private\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @param {Boolean} isRightCurry\n * @param {Boolean} isAutoCurry\n */\n function _curry (fn, arity, isRightCurry, isAutoCurry) {\n var slicer = isAutoCurry ? function (argsObj) {\n var len = argsObj.length;\n\n if (len) {\n for (var i = 0, args = []; i < len; i++) {\n args[i] = argsObj[i];\n }\n\n return args;\n } else {\n return [void 0];\n }\n } : function (argsObj) {\n return argsObj.length ? [argsObj[0]] : [void 0];\n };\n\n if ((arity >>> 0) !== arity) {\n arity = fn.length;\n }\n\n return arity > 1 ? _currier(fn, arity, isRightCurry, slicer, []) : fn;\n }\n\n /**\n * Flattens an array.\n * @private\n * @param {Array} array\n * @param {Array} output The empty array to collect the result\n * @returns {Array} The output array filled with the results\n */\n function _flatten (array, output) {\n forEach(array, function (value) {\n if (Array.isArray(value)) {\n _flatten(value, output);\n } else {\n output.push(value);\n }\n });\n\n return output;\n }\n\n /**\n * Establishes at which index an element should be inserted in a sorted array to respect\n * the array order. Needs the comparer used to sort the array.\n * @param {Array} array\n * @param {*} element\n * @param {Function} comparer\n * @param {Number} start\n * @param {Number} end\n * @private\n */\n function _getInsertionIndex (array, element, comparer, start, end) {\n if (array.length === 0) {\n return 0;\n }\n\n var pivot = (start + end) >> 1;\n var result = comparer({\n value: element,\n index: pivot\n }, {\n value: array[pivot],\n index: pivot\n });\n\n if (end - start <= 1) {\n return result < 0 ? pivot : pivot + 1;\n } else if (result < 0) {\n return _getInsertionIndex(array, element, comparer, start, pivot);\n } else if (result === 0) {\n return pivot + 1;\n } else {\n return _getInsertionIndex(array, element, comparer, pivot, end);\n }\n }\n\n /**\n * Checks if the given index, even negative, exists in the target object, if\n * it's an array-like, and transforms it to a natural number.\n * Returns undefined otherwise.\n * @private\n * @param {ArrayLike} target\n * @param {Number} index\n * @returns {Number|undefined}\n */\n function _getNaturalIndex (target, index) {\n var len = target.length;\n\n if (_isInteger(index) && _isInteger(len)) {\n return clamp(index, -len, len - 1) === index ? index < 0 ? index + len : index : void 0;\n }\n }\n\n /**\n * Gets the number of consecutive elements satisfying a predicate in an array-like object.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {Function} predicate\n * @param {Object} predicateContext\n */\n function _getNumConsecutiveHits (arrayLike, predicate, predicateContext) {\n var idx = -1;\n var len = arrayLike.length;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n while (++idx < len && predicate(arrayLike[idx], idx, arrayLike));\n\n return idx;\n }\n\n /**\n * Builds the prefix or suffix to be used when padding a string.\n * @private\n * @param {String} source\n * @param {String} char\n * @param {Number} len\n * @returns {String}\n */\n function _getPadding (source, char, len) {\n if (!isNil(source) && type(source) !== \"String\") {\n source = String(source);\n }\n\n return repeat(Object(char)[0] || \" \", Math.ceil(len - source.length));\n }\n\n /**\n * Checks if a path is valid in the given object and retrieves the path target.\n * @private\n * @param {Object} obj\n * @param {String[]} parts\n * @param {Boolean} walkNonEnumerables\n * @returns {Object}\n */\n function _getPathInfo (obj, parts, walkNonEnumerables) {\n var target = obj;\n var i = -1;\n var len = parts.length;\n var key;\n var keyAsNumber;\n\n while (++i < len) {\n key = parts[i];\n\n if (!(_isEnumerable(target, key) || key in Object(target) && walkNonEnumerables)) {\n keyAsNumber = Number(key);\n key = keyAsNumber < 0 ? _getNaturalIndex(target, keyAsNumber) : void 0;\n }\n\n if (isUndefined(key)) {\n break;\n }\n\n target = target[key];\n }\n\n return i === len ? {isValid: true, target: target} : {isValid: false, target: void 0};\n }\n\n /**\n * Builds a \"grouping function\" for an array-like object.\n * @private\n * @param {Function} makeValue\n * @param {*} startValue\n * @returns {Function}\n */\n function _groupWith (makeValue, startValue) {\n return function (arrayLike, iteratee, iterateeContext) {\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n return reduce(arrayLike, function (result, element, idx) {\n var key = iteratee(element, idx, arrayLike);\n var value = makeValue(key in result ? result[key] : startValue , element);\n\n result[key] = value;\n\n return result;\n }, {});\n };\n }\n\n /**\n * Makes an object immutable by recursively calling Object.freeze\n * on its members.\n * @private\n * @param {Object} obj\n * @param {Array} seen\n * @returns {Object} The obj parameter itself, not a copy.\n */\n function _immutable (obj, seen) {\n if (seen.indexOf(obj) === -1) {\n seen.push(Object.freeze(obj));\n\n forEach(Object.getOwnPropertyNames(obj), function (key) {\n var value = obj[key];\n\n if (typeof value === \"object\" && !isNull(value)) {\n _immutable(value, seen);\n }\n });\n }\n\n return obj;\n }\n\n /**\n * If a method with the given name exists on the target, applies it with the provided\n * arguments and returns the result. Returns undefined otherwise.
\n * The arguments for the method are built by concatenating the array of bound arguments,\n * optionally received by {@link module:lamb.invoker|invoker}, with the final set of, also\n * optional, args.\n * @private\n * @param {Array} boundArgs\n * @param {String} methodName\n * @param {Object} target\n * @param {...*} [args]\n * @returns {*}\n */\n function _invoker (boundArgs, methodName, target) {\n var args = boundArgs.concat(slice(arguments, 3));\n var method = target[methodName];\n return type(method) === \"Function\" ? method.apply(target, args) : void 0;\n }\n\n /**\n * Accepts a target object and a key name and verifies that the target is an array and that\n * the key is an existing index.\n * @private\n * @param {Object} target\n * @param {String|Number} key\n * @returns {Boolean}\n */\n function _isArrayIndex (target, key) {\n var n = Number(key);\n return Array.isArray(target) && _isInteger(n) && !(n < 0 && _isEnumerable(target, key));\n }\n\n /**\n * Checks whether the specified key is an enumerable property of the given object or not.\n * @private\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n function _isEnumerable (obj, key) {\n return key in Object(obj) && (_isOwnEnumerable(obj, key) || ~_safeEnumerables(obj).indexOf(key));\n }\n\n /**\n * Checks if the given value is an integer.\n * @private\n * @param {*} n\n * @returns {Boolean}\n */\n function _isInteger (n) {\n return Math.floor(n) === n;\n }\n\n /**\n * Checks whether the specified key is a own enumerable property of the given object or not.\n * @private\n * @function\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n var _isOwnEnumerable = generic(_objectProto.propertyIsEnumerable);\n\n /**\n * Accepts an object and build a function expecting a key to create a \"pair\" with the key\n * and its value.\n * @private\n * @param {Object} obj\n * @returns {Function}\n */\n function _keyToPairIn (obj) {\n return function (key) {\n return [key, obj[key]];\n };\n }\n\n /**\n * Builds a list of sorting criteria from a list of sorter functions. Returns a list containing\n * a single default sorting criterion if the sorter list is empty.\n * @private\n * @param {Function[]} sorters\n * @returns {Sorter[]}\n */\n function _makeCriteria (sorters) {\n return sorters.length ? map(sorters, _makeCriterion) : [_sorter()];\n }\n\n /**\n * Converts a sorting function to a sorting criterion if necessary.\n * @private\n * @param {Function} criterion\n * @returns {Sorter}\n */\n function _makeCriterion (criterion) {\n return typeof Object(criterion).compare === \"function\" ? criterion : _sorter(criterion);\n }\n\n /**\n * Builds a reduce function. The step parameter must be 1\n * to build {@link module:lamb.reduce|reduce} and -1 to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\n function _makeReducer (step) {\n return function (arrayLike, accumulator, initialValue) {\n var len = arrayLike.length >>> 0;\n var idx = step === 1 ? 0 : len - 1;\n var nCalls;\n var result;\n\n if (arguments.length === 3) {\n nCalls = len;\n result = initialValue;\n } else {\n if (len === 0) {\n throw new TypeError(\"Reduce of empty array-like with no initial value\");\n }\n\n result = arrayLike[idx];\n idx += step;\n nCalls = len - 1;\n }\n\n for (; nCalls--; idx += step) {\n result = accumulator(result, arrayLike[idx], idx, arrayLike);\n }\n\n return result;\n };\n }\n\n /**\n * Builds a TypeError stating that it's not possible to convert the given value to the\n * desired type.\n * @private\n * @param {*} value\n * @param {String} desiredType\n * @returns {TypeError}\n */\n function _makeTypeErrorFor(value, desiredType) {\n return new TypeError(\"Cannot convert \" + type(value).toLowerCase() + \" to \" + desiredType);\n }\n\n /**\n * Merges the received objects using the provided functions to retrieve their keys.\n * @private\n * @param {Function} getKeys\n * @param {...Object} source\n * @returns {Object}\n */\n function _merge (getKeys) {\n return reduce(slice(arguments, 1), function (result, source) {\n forEach(getKeys(source), function (key) {\n result[key] = source[key];\n });\n\n return result;\n }, {});\n }\n\n /**\n * Using the provided function to retrieve the keys of an object, builds\n * a function expecting an object to create a list of key / value pairs.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _pairsFrom = _curry(function (getKeys, obj) {\n return map(getKeys(obj), _keyToPairIn(obj));\n });\n\n /**\n * Builds a partial application of a function expecting an iteratee and an\n * optional argument other than its main data parameter.
\n * The optional argument is passed to the function only when is explicitly given\n * a value.
\n * The optional argument is usually the iteratee context, but reduce functions\n * pass their initial value instead.\n * @private\n * @param {Function} fn\n * @returns {Function}\n */\n function _partialWithIteratee (fn) {\n return function (iteratee, optionalArgument) {\n var f = arguments.length === 2 ? fn : binary(fn);\n return partial(f, _, iteratee, optionalArgument);\n };\n }\n\n /**\n * Builds a list of the enumerable properties of an object.\n * The function is null-safe, unlike the public one.\n * @private\n * @param {Object} obj\n * @returns {String[]}\n */\n function _safeEnumerables (obj) {\n var keys = [];\n\n for (var key in obj) {\n keys.push(key);\n }\n\n return keys;\n }\n\n /**\n * A null-safe version of Object.keys.\n * @private\n * @param {Object} obj\n * @returns {String[]}\n */\n var _safeKeys = compose(Object.keys, Object);\n\n /**\n * Sets an index in an array-like object.
\n * If provided with an updater function it will use it to update the current value,\n * otherwise sets the index to the specified value.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} [value]\n * @param {Function} [updater]\n */\n function _setIndex (arrayLike, index, value, updater) {\n var result = slice(arrayLike);\n var idx = _getNaturalIndex(result, index);\n var isUpdate = arguments.length === 4;\n\n if (!isUndefined(idx)) {\n result[idx] = isUpdate ? updater(arrayLike[idx]) : value;\n }\n\n return result;\n }\n\n /**\n * Sets the object's property targeted by the given path to the desired value.
\n * Works with arrays and is able to set their indexes, even negative ones.\n * @private\n * @param {Object|Array} obj\n * @param {String[]} parts\n * @param {*} value\n * @returns {Object|Array}\n */\n function _setPathIn (obj, parts, value) {\n var key = parts[0];\n var v = parts.length === 1 ? value : _setPathIn(\n _getPathInfo(obj, [key], false).target,\n slice(parts, 1),\n value\n );\n\n return _isArrayIndex(obj, key) ? _setIndex(obj, +key, v) : setIn(Object(obj), key, v);\n }\n\n /**\n * Builds a sorting criterion. If the comparer function is missing, the default\n * comparer will be used instead.\n * @param {Function} reader\n * @param {Boolean} isDescending\n * @param {Function} [comparer]\n * @private\n */\n function _sorter (reader, isDescending, comparer) {\n return {\n isDescending: isDescending === true,\n compare: function (a, b) {\n if (typeof reader === \"function\" && reader !== identity) {\n a = reader(a);\n b = reader(b);\n }\n\n return (typeof comparer === \"function\" ? comparer : _comparer)(a, b);\n }\n };\n }\n\n /**\n * Using the provided function to retrieve the keys of an object, builds\n * a function expecting an object to create an array containing a list\n * of the keys in its first index and the corresponding list of values\n * in the second one.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _tearFrom = _curry(function (getKeys, obj) {\n return reduce(getKeys(obj), function (result, key) {\n result[0].push(key);\n result[1].push(obj[key]);\n return result;\n }, [[], []]);\n });\n\n /**\n * Splits a sting path using the provided separator and returns an array\n * of path parts.\n * @private\n * @param {String} path\n * @param {String} separator\n * @returns {String[]}\n */\n function _toPathParts (path, separator) {\n return String(path).split(separator || \".\");\n }\n\n /**\n * Creates a non-null-safe version of the provided \"getKeys\" function.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _unsafeKeyListFrom = _curry(function (getKeys, obj) {\n return (isNil(obj) ? Object.keys : getKeys)(obj);\n });\n\n /**\n * Using the provided function to retrieve the keys of an object, builds\n * a function expecting an object to create the list of values for such keys.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _valuesFrom = _curry(function (getKeys, obj) {\n return map(getKeys(obj), partial(getIn, obj));\n });\n\n\n /**\n * Builds an array comprised of all values of the array-like object passing the predicate test.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.filter]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * var isLowerCase = function (s) { return s.toLowerCase() === s; };\n *\n * _.filter([\"Foo\", \"bar\", \"baZ\"], isLowerCase) // => [\"bar\"]\n *\n * // the function will work with any array-like object\n * _.filter(\"fooBAR\", isLowerCase) // => [\"f\", \"o\", \"o\"]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.filterWith|filterWith}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Array}\n */\n function filter (arrayLike, predicate, predicateContext) {\n var len = arrayLike.length;\n var result = [];\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0; i < len; i++) {\n predicate(arrayLike[i], i, arrayLike) && result.push(arrayLike[i]);\n }\n\n return result;\n }\n\n /**\n * Returns a partial application of {@link module:lamb.filter|filter} that uses the given predicate and\n * the optional context to build a function expecting the array-like object to act upon.\n * @example\n * var isLowerCase = function (s) { return s.toLowerCase() === s; };\n * var getLowerCaseEntries = _.filterWith(isLowerCase);\n *\n * getLowerCaseEntries([\"Foo\", \"bar\", \"baZ\"]) // => [\"bar\"]\n *\n * // array-like objects can be used as well\n * getLowerCaseEntries(\"fooBAR\") // => [\"f\", \"o\", \"o\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.filter|filter}\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n var filterWith = _partialWithIteratee(filter);\n\n /**\n * Executes the provided iteratee for each element of the given array-like object.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.forEach]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example Adding a CSS class to all elements of a NodeList in a browser environment\n * var addClass = _.curry(function (className, element) {\n * element.classList.add(className);\n * });\n * var paragraphs = document.querySelectorAll(\"#some-container p\");\n *\n * _.forEach(paragraphs, addClass(\"main\"));\n * // each \"p\" element in the container will have the \"main\" class now\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n */\n function forEach (arrayLike, iteratee, iterateeContext) {\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n for (var i = 0, len = arrayLike.length >>> 0; i < len; i++) {\n iteratee(arrayLike[i], i, arrayLike);\n }\n }\n\n /**\n * Builds a new array by applying the iteratee function to each element of the\n * received array-like object.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.map]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * _.map([\"Joe\", \"Mario\", \"Jane\"], _.invoker(\"toUpperCase\")) // => [\"JOE\", \"MARIO\", \"JANE\"]\n *\n * _.map([4, 9, 16], Math.sqrt); // => [2, 3, 4]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.mapWith|mapWith}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n function map (arrayLike, iteratee, iterateeContext) {\n var len = arrayLike.length >>> 0;\n var result = Array(len);\n\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n for (var i = 0; i < len; i++) {\n result[i] = iteratee(arrayLike[i], i, arrayLike);\n }\n\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.map|map} using the given iteratee and the optional context.\n * The resulting function expects the array-like object to act upon.\n * @example\n * var square = function (n) { return n * n; };\n * var getSquares = _.mapWith(square);\n *\n * getSquares([1, 2, 3, 4, 5]) // => [1, 4, 9, 16, 25]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.map|map}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {function}\n */\n var mapWith = _partialWithIteratee(map);\n\n /**\n * Reduces (or folds) the values of an array-like object, starting from the first, to a new\n * value using the provided accumulator function.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.reduce]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * _.reduce([1, 2, 3, 4], _.add) // => 10\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduceRight|reduceRight}\n * @see {@link module:lamb.reduceWith|reduceWith}, {@link module:lamb.reduceRightWith|reduceRightWith}\n * @param {ArrayLike} arrayLike\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {*}\n */\n var reduce = _makeReducer(1);\n\n /**\n * Same as {@link module:lamb.reduce|reduce}, but starts the fold operation from the last element instead.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.reduceRight]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduce|reduce}\n * @see {@link module:lamb.reduceWith|reduceWith}, {@link module:lamb.reduceRightWith|reduceRightWith}\n * @param {ArrayLike} arrayLike\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {*}\n */\n var reduceRight = _makeReducer(-1);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduceRight} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.reduceRightWith(_.add)(arr) // => 15\n * _.reduceRightWith(_.subtract)(arr) // => -5\n * _.reduceRightWith(_.subtract, 0)(arr) // => -15\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduceWith|reduceWith}\n * @see {@link module:lamb.reduce|reduce}, {@link module:lamb.reduce|reduceRight}\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {Function}\n */\n var reduceRightWith = _partialWithIteratee(reduceRight);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduce} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.reduceWith(_.add)(arr) // => 15\n * _.reduceWith(_.subtract)(arr) // => -13\n * _.reduceWith(_.subtract, 0)(arr) // => -15\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduceRightWith|reduceRightWith}\n * @see {@link module:lamb.reduce|reduce}, {@link module:lamb.reduce|reduceRight}\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {Function}\n */\n var reduceWith = _partialWithIteratee(reduce);\n\n /**\n * Builds an array by extracting a portion of an array-like object.
\n * It's a generic version of [Array.prototype.slice]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice}.\n * @example\n * _.slice([\"foo\", \"bar\", \"baz\"], 0, 2) // => [\"foo\", \"bar\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {ArrayLike} arrayLike - Any array like object.\n * @param {Number} [start=0] - Zero-based index at which to begin extraction.\n * @param {Number} [end=arrayLike.length] - Zero-based index at which to end extraction. Extracts up to but not including end.\n * @returns {Array}\n */\n var slice = generic(_arrayProto.slice);\n\n lamb.filter = filter;\n lamb.filterWith = filterWith;\n lamb.forEach = forEach;\n lamb.map = map;\n lamb.mapWith = mapWith;\n lamb.reduce = reduce;\n lamb.reduceRight = reduceRight;\n lamb.reduceRightWith = reduceRightWith;\n lamb.reduceWith = reduceWith;\n lamb.slice = slice;\n\n\n /**\n * Accepts a series of functions and builds a function that applies the received arguments to each one and\n * returns the first non-undefined value.
\n * Meant to work in sinergy with {@link module:lamb.condition|condition} and {@link module:lamb.invoker|invoker},\n * can be useful as a strategy pattern for functions, to mimic conditional logic and also to build polymorphic functions.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var filterString = _.compose(_.invoker(\"join\", \"\"), _.filter);\n * var filterAdapter = _.adapter(\n * _.invoker(\"filter\"),\n * _.condition(_.isType(\"String\"), filterString)\n * );\n *\n * filterAdapter([1, 2, 3, 4, 5, 6], isEven) // => [2, 4, 6]\n * filterAdapter(\"123456\", isEven) // => \"246\"\n * filterAdapter({}, isEven) // => undefined\n *\n * // obviously it's composable\n * var filterWithDefault = _.adapter(filterAdapter, _.always(\"Not implemented\"));\n *\n * filterWithDefault([1, 2, 3, 4, 5, 6], isEven) // => [2, 4, 6]\n * filterWithDefault(\"123456\", isEven) // => \"246\"\n * filterWithDefault({}, isEven) // => \"Not implemented\"\n *\n * @memberof module:lamb\n * @category Logic\n * @param {...Function} fn\n * @returns {Function}\n */\n function adapter () {\n var functions = slice(arguments);\n\n return function () {\n var len = functions.length;\n var result;\n\n for (var i = 0; i < len; i++) {\n result = functions[i].apply(this, arguments);\n\n if (!isUndefined(result)) {\n break;\n }\n }\n\n return result;\n };\n }\n\n /**\n * Builds a predicate that returns true if all the given predicates are satisfied.\n * The arguments passed to the resulting function are applied to every predicate unless one of them returns false.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var isPositive = function (n) { return n > 0; };\n * var isPositiveEven = _.allOf(isEven, isPositive);\n *\n * isPositiveEven(-2) // => false\n * isPositiveEven(11) // => false\n * isPositiveEven(6) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.anyOf|anyOf}\n * @param {...Function} predicate\n * @returns {Function}\n */\n function allOf () {\n var predicates = slice(arguments);\n\n return function () {\n for (var i = 0, len = predicates.length; i < len; i++) {\n if(!predicates[i].apply(this, arguments)) {\n return false;\n }\n }\n\n return true;\n };\n }\n\n /**\n * Builds a predicate that returns true if at least one of the given predicates is satisfied.\n * The arguments passed to the resulting function are applied to every predicate until one of them returns true.\n * @example\n * var users = [\n * {id: 1, name: \"John\", group: \"guest\"},\n * {id: 2, name: \"Jane\", group: \"root\"},\n * {id: 3, name: \"Mario\", group: \"admin\"}\n * ];\n * var isInGroup = _.partial(_.hasKeyValue, \"group\");\n * var isSuperUser = _.anyOf(isInGroup(\"admin\"), isInGroup(\"root\"));\n *\n * isSuperUser(users[0]) // => false\n * isSuperUser(users[1]) // => true\n * isSuperUser(users[2]) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.allOf|allOf}\n * @param {...Function} predicate\n * @returns {Function}\n */\n function anyOf () {\n var predicates = slice(arguments);\n\n return function () {\n for (var i = 0, len = predicates.length; i < len; i++) {\n if (predicates[i].apply(this, arguments)) {\n return true;\n }\n }\n\n return false;\n };\n }\n\n /**\n * Builds a function that will apply the received arguments to trueFn, if the predicate is satisfied with\n * the same arguments, or to falseFn otherwise.
\n * If falseFn isn't provided and the predicate isn't satisfied the function will return undefined.
\n * Although you can use other conditions as trueFn or falseFn, it's probably better to\n * use {@link module:lamb.adapter|adapter} to build more complex behaviours.\n * @example\n * var isEven = function (n) { return n % 2 === 0};\n * var halve = function (n) { return n / 2; };\n * var halveIfEven = _.condition(isEven, halve, _.identity);\n *\n * halveIfEven(5) // => 5\n * halveIfEven(6) // => 3\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.invoker|invoker}\n * @param {Function} predicate\n * @param {Function} trueFn\n * @param {Function} [falseFn]\n * @returns {Function}\n */\n function condition (predicate, trueFn, falseFn) {\n return function () {\n var applyArgsTo = applyArgs(arguments);\n return applyArgsTo(predicate) ? applyArgsTo(trueFn) : falseFn ? applyArgsTo(falseFn) : void 0;\n };\n }\n\n /**\n * Verifies that the two supplied values are the same value using the \"SameValue\" comparison.
\n * Note that this doesn't behave as the strict equality operator, but rather as a shim of ES6's\n * [Object.is]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is}.\n * Differences are that 0 and -0 aren't the same value and, finally, NaN is equal to itself.
\n * See also {@link module:lamb.isSVZ|isSVZ} which performs the check using the \"SameValueZero\" comparison.\n * @example\n * var testObject = {};\n *\n * _.is({}, testObject) // => false\n * _.is(testObject, testObject) // => true\n * _.is(\"foo\", \"foo\") // => true\n * _.is(0, -0) // => false\n * _.is(0 / 0, NaN) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see [SameValue comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero}\n * @param {*} a\n * @param {*} b\n * @returns {Boolean}\n */\n function is (a, b) {\n return a === 0 && b === 0 ? 1 / a === 1 / b : isSVZ(a, b);\n }\n\n /**\n * Verifies that the first given value is greater than the second.\n * @example\n * var pastDate = new Date(2010, 2, 12);\n * var today = new Date();\n *\n * _.isGT(today, pastDate) // true\n * _.isGT(pastDate, today) // false\n * _.isGT(3, 4) // false\n * _.isGT(3, 3) // false\n * _.isGT(3, 2) // true\n * _.isGT(0, -0) // false\n * _.isGT(-0, 0) // false\n * _.isGT(\"a\", \"A\") // true\n * _.isGT(\"b\", \"a\") // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isGT (a, b) {\n return a > b;\n }\n\n /**\n * Verifies that the first given value is greater than or equal to the second.\n * Regarding equality, beware that this is simply a wrapper for the native operator, so -0 === 0.\n * @example\n * _.isGTE(3, 4) // false\n * _.isGTE(3, 3) // true\n * _.isGTE(3, 2) // true\n * _.isGTE(0, -0) // true\n * _.isGTE(-0, 0) // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isGTE (a, b) {\n return a >= b;\n }\n\n /**\n * Verifies that the first given value is less than the second.\n * @example\n * var pastDate = new Date(2010, 2, 12);\n * var today = new Date();\n *\n * _.isLT(today, pastDate) // false\n * _.isLT(pastDate, today) // true\n * _.isLT(3, 4) // true\n * _.isLT(3, 3) // false\n * _.isLT(3, 2) // false\n * _.isLT(0, -0) // false\n * _.isLT(-0, 0) // false\n * _.isLT(\"a\", \"A\") // false\n * _.isLT(\"a\", \"b\") // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isLT (a, b) {\n return a < b;\n }\n\n /**\n * Verifies that the first given value is less than or equal to the second.\n * Regarding equality, beware that this is simply a wrapper for the native operator, so -0 === 0.\n * @example\n * _.isLTE(3, 4) // true\n * _.isLTE(3, 3) // true\n * _.isLTE(3, 2) // false\n * _.isLTE(0, -0) // true\n * _.isLTE(-0, 0) // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isLTE (a, b) {\n return a <= b;\n }\n\n /**\n * A simple negation of {@link module:lamb.is|is}, exposed for convenience.\n * @example\n * _.isNot(\"foo\", \"foo\") // => false\n * _.isNot(0, -0) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @param {*} valueA\n * @param {*} valueB\n * @returns {Boolean}\n */\n var isNot = not(is);\n\n /**\n * Verifies that the two supplied values are the same value using the \"SameValueZero\" comparison.
\n * With this comparison NaN is equal to itself, but 0 and -0 are\n * considered the same value too.
\n * See also {@link module:lamb.is|is} to perform a \"SameValue\" comparison.\n * @example\n * var testObject = {};\n *\n * _.isSVZ({}, testObject) // => false\n * _.isSVZ(testObject, testObject) // => true\n * _.isSVZ(\"foo\", \"foo\") // => true\n * _.isSVZ(0, -0) // => true\n * _.isSVZ(0 / 0, NaN) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see [SameValue comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero}\n * @param {*} a\n * @param {*} b\n * @returns {Boolean}\n */\n function isSVZ (a, b) {\n return a !== a ? b !== b : a === b;\n }\n\n /**\n * Returns a predicate that negates the given one.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var isOdd = _.not(isEven);\n *\n * isOdd(5) // => true\n * isOdd(4) // => false\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Function} predicate\n * @returns {Function}\n */\n function not (predicate) {\n return function () {\n return !predicate.apply(this, arguments);\n };\n }\n\n lamb.adapter = adapter;\n lamb.allOf = allOf;\n lamb.anyOf = anyOf;\n lamb.condition = condition;\n lamb.is = is;\n lamb.isGT = isGT;\n lamb.isGTE = isGTE;\n lamb.isLT = isLT;\n lamb.isLTE = isLTE;\n lamb.isNot = isNot;\n lamb.isSVZ = isSVZ;\n lamb.not = not;\n\n\n /**\n * Adds two numbers.\n * @example\n * _.add(4, 5) // => 9\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function add (a, b) {\n return a + b;\n }\n\n /**\n * \"Clamps\" a number within the given limits.\n * @example\n * _.clamp(-5, 0, 10) // => 0\n * _.clamp(5, 0, 10) // => 5\n * _.clamp(15, 0, 10) // => 10\n * _.clamp(0, 0, 10) // => 0\n * _.clamp(10, 0, 10) // => 10\n * _.is(_.clamp(-0, 0, 10), -0) // => true\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} n\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n function clamp (n, min, max) {\n return n < min ? min : n > max ? max : n;\n }\n\n /**\n * Divides two numbers.\n * @example\n * _.divide(5, 2) // => 2.5\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function divide (a, b) {\n return a / b;\n }\n\n /**\n * Generates a sequence of values of the desired length with the provided iteratee.\n * The values being iterated, and received by the iteratee, are the results generated so far.\n * @example\n * var fibonacci = function (n, idx, results) {\n * return n + (results[idx - 1] || 0);\n * };\n *\n * _.generate(1, 10, fibonacci) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n *\n * @memberof module:lamb\n * @category Math\n * @param {*} start - The starting value\n * @param {Number} len - The desired length for the sequence\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n function generate (start, len, iteratee, iterateeContext) {\n var result = [start];\n\n if (arguments.length === 4) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n for (var i = 0, limit = len - 1; i < limit; i++) {\n result.push(iteratee(result[i], i, result));\n }\n\n return result;\n }\n\n /**\n * Performs the modulo operation and should not be confused with the {@link module:lamb.remainder|remainder}.\n * The function performs a floored division to calculate the result and not a truncated one, hence the sign of\n * the dividend is not kept, unlike the {@link module:lamb.remainder|remainder}.\n * @example\n * _.modulo(5, 3) // => 2\n * _.remainder(5, 3) // => 2\n *\n * _.modulo(-5, 3) // => 1\n * _.remainder(-5, 3) // => -2\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link http://en.wikipedia.org/wiki/Modulo_operation}\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function modulo (a, b) {\n return a - (b * Math.floor(a / b));\n }\n\n /**\n * Multiplies two numbers.\n * @example\n * _.multiply(5, 3) // => 15\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function multiply (a, b) {\n return a * b;\n }\n\n /**\n * Generates a random integer between two given integers, both included.\n * Note that no safety measure is taken if the provided arguments aren't integers, so\n * you may end up with unexpected (not really) results.\n * For example randomInt(0.1, 1.2) could be 2.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n function randomInt (min, max) {\n return Math.floor(Math.random() * (max - min + 1) + min);\n }\n\n /**\n * Generates an arithmetic progression of numbers starting from start up to,\n * but not including, limit, using the given step.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(2, 10, 0) // => [2]\n * _.range(1, -10, -2) // => [1, -1, -3, -5, -7, -9]\n * _.range(1, -10, 2) // => [1]\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} start\n * @param {Number} limit\n * @param {Number} [step=1]\n * @returns {Number[]}\n */\n function range (start, limit, step) {\n if (step === 0 || arguments.length < 2) {\n return [start];\n }\n\n if (!step) {\n step = 1;\n }\n\n var len = Math.max(Math.ceil((limit - start) / step), 0);\n return generate(start, len, partial(add, step));\n }\n\n /**\n * Gets the remainder of the division of two numbers.\n * Not to be confused with the {@link module:lamb.modulo|modulo} as the remainder\n * keeps the sign of the dividend and may lead to some unexpected results.\n * @example\n * // example of wrong usage of the remainder\n * // (in this case the modulo operation should be used)\n * var isOdd = function (n) { return _.remainder(n, 2) === 1; };\n * isOdd(-3) // => false as -3 % 2 === -1\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link http://en.wikipedia.org/wiki/Modulo_operation}\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function remainder (a, b) {\n return a % b;\n }\n\n /**\n * Subtracts two numbers.\n * @example\n * _.subtract(5, 3) // => 2\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function subtract (a, b) {\n return a - b;\n }\n\n lamb.add = add;\n lamb.clamp = clamp;\n lamb.divide = divide;\n lamb.generate = generate;\n lamb.modulo = modulo;\n lamb.multiply = multiply;\n lamb.randomInt = randomInt;\n lamb.range = range;\n lamb.remainder = remainder;\n lamb.subtract = subtract;\n\n\n /**\n * Verifies if a value is null or undefined.\n * @example\n * _.isNil(NaN) // => false\n * _.isNil({}) // => false\n * _.isNil(null) // => true\n * _.isNil(void 0) // => true\n * _.isNil() // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNull|isNull} and {@link module:lamb.isNull|isUndefined} for individual checks.\n * @param {*} value\n * @returns {Boolean}\n */\n function isNil (value) {\n return isNull(value) || isUndefined(value);\n }\n\n /**\n * Verifies if a value is null.\n * @example\n * _.isNull(null) // => true\n * _.isNull(void 0) // => false\n * _.isNull(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for undefined too.\n * @param {*} value\n * @returns {Boolean}\n */\n function isNull (value) {\n return value === null;\n }\n\n /**\n * Builds a predicate that expects a value to check against the specified type.\n * @example\n * var isString = _.isType(\"String\");\n *\n * isString(\"Hello\") // => true\n * isString(new String(\"Hi\")) // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.type|type}\n * @param {String} typeTag\n * @returns {Function}\n */\n function isType (typeName) {\n return function (value) {\n return type(value) === typeName;\n };\n }\n\n /**\n * Verifies if a value is undefined.\n * @example\n * _.isUndefined(null) // => false\n * _.isUndefined(void 0) // => true\n * _.isUndefined(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for null too.\n * @param {*} value\n * @returns {Boolean}\n */\n function isUndefined (value) {\n // using void because undefined could be theoretically shadowed\n return value === void 0;\n }\n\n /**\n * Retrieves the \"type tag\" from the given value.\n * @example\n * var x = 5;\n * var y = new Number(5);\n *\n * typeof x // => \"number\"\n * typeof y // => \"object\"\n * _.type(x) // => \"Number\"\n * _.type(y) // => \"Number\"\n *\n * _.type(Object.prototype.toString) // => \"Function\"\n * _.type(/a/) // => \"RegExp\"\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isType|isType}\n * @param {*} value\n * @returns {String}\n */\n function type (value) {\n return _objectProto.toString.call(value).replace(/^\\[\\w+\\s+|\\]$/g, \"\");\n }\n\n lamb.isNil = isNil;\n lamb.isNull = isNull;\n lamb.isType = isType;\n lamb.isUndefined = isUndefined;\n lamb.type = type;\n\n\n /**\n * A curried version of {@link module:lamb.getIndex|getIndex} that uses the provided index\n * to build a function expecting the array-like object holding the element we want to retrieve.\n * @example\n * var getFifthElement = _.getAt(4);\n *\n * getFifthElement([1, 2, 3, 4, 5]) // => 5\n * getFifthElement(\"foo bar\") // => \"b\"\n * getFifthElement([]) // => undefined\n * getFifthElement(\"foo\") // => undefined\n *\n * @example Using negative indexes\n * _.getAt(-2)([1, 2, 3]) // => 2\n * _.getAt(-3)(\"foo\") // => \"f\"\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.getIndex|getIndex}\n * @see {@link module:lamb.head|head} and {@link module:lamb.last|last} for common use cases shortcuts.\n * @param {Number} index\n * @returns {Function}\n */\n function getAt (index) {\n return function (arrayLike) {\n return getIndex(arrayLike, index);\n };\n }\n\n /**\n * Returns the value of the object property with the given key.\n * @example\n * var user = {name: \"John\"};\n *\n * _.getIn(user, \"name\") // => \"John\";\n * _.getIn(user, \"surname\") // => undefined\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getKey|getKey}\n * @see {@link module:lamb.getPath|getPath}, {@link module:lamb.getPathIn|getPathIn}\n * @param {Object} obj\n * @param {String} key\n * @returns {*}\n */\n function getIn (obj, key) {\n return obj[key];\n }\n\n /**\n * Retrieves the element at the given index in an array-like object.
\n * Like {@link module:lamb.slice|slice} the index can be negative.
\n * If the index isn't supplied, or if its value isn't an integer within the array-like bounds,\n * the function will return undefined.
\n * getIndex will throw an exception when receives null or\n * undefined in place of an array-like object, but returns undefined\n * for any other value.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.getIndex(arr, 1) // => 2\n * _.getIndex(arr, -1) // => 5\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.getAt|getAt}\n * @see {@link module:lamb.head|head} and {@link module:lamb.last|last} for common use cases shortcuts.\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @returns {*}\n */\n function getIndex (arrayLike, index) {\n var idx = _getNaturalIndex(arrayLike, index);\n return isUndefined(idx) ? idx : arrayLike[idx];\n }\n\n /**\n * A curried version of {@link module:lamb.getIn|getIn}.
\n * Receives a property name and builds a function expecting the object from which we want to retrieve the property.\n * @example\n * var user1 = {name: \"john\"};\n * var user2 = {name: \"jane\"};\n * var getName = _.getKey(\"name\");\n *\n * getName(user1) // => \"john\"\n * getName(user2) // => \"jane\"\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getIn|getIn}\n * @see {@link module:lamb.getPath|getPath}, {@link module:lamb.getPathIn|getPathIn}\n * @param {String} key\n * @returns {Function}\n */\n function getKey (key) {\n return function (obj) {\n return getIn(obj, key);\n };\n }\n\n /**\n * Builds a partial application of {@link module:lamb.getPathIn|getPathIn} with the given\n * path and separator, expecting the object to act upon.
\n * @example\n * var user = {\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * \"user.name\": \"jdoe\",\n * password: \"abc123\"\n * }\n * };\n *\n * var getPwd = _.getPath(\"login.password\");\n * var getUsername = _.getPath(\"login/user.name\", \"/\");\n *\n * getPwd(user) // => \"abc123\";\n * getUsername(user) // => \"jdoe\"\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPathIn|getPathIn}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\n function getPath (path, separator) {\n return partial(getPathIn, _, path, separator);\n }\n\n /**\n * Gets a nested property value from an object using the given path.
\n * The path is a string with property names separated by dots by default, but\n * it can be customised with the optional third parameter.
\n * You can use integers in the path, even negative ones, to refer to array-like\n * object indexes, but the priority will be given to existing object keys:\n * the last example explains this particular case.\n * @example\n * var user = {\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * \"user.name\": \"jdoe\",\n * password: \"abc123\"\n * },\n * scores: [\n * {id: 1, value: 10},\n * {id: 2, value: 20},\n * {id: 3, value: 30}\n * ]\n * };\n *\n * _.getPathIn(user, \"name\") // => \"John\"\n * _.getPathIn(user, \"login.password\") // => \"abc123\";\n * _.getPathIn(user, \"login/user.name\", \"/\") // => \"jdoe\"\n * _.getPathIn(user, \"name.foo\") // => undefined\n * _.getPathIn(user, \"name.foo.bar\") // => undefined\n *\n * @example Accessing array-like objects indexes:\n * _.getPathIn(user, \"login.password.1\") // => \"b\"\n * _.getPathIn(user, \"scores.0\") // => {id: 1, value: 10}\n * _.getPathIn(user, \"scores.-1.value\") // => 30\n *\n * @example Priority will be given to existing object keys over indexes:\n * _.getPathIn(user, \"scores.-1\") // => {id: 3, value: 30}\n *\n * // let's do something funny\n * user.scores[\"-1\"] = \"foo bar\";\n *\n * _.getPathIn(user, \"scores.-1\") // => \"foo bar\";\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPath|getPath}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @param {Object|ArrayLike} obj\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {*}\n */\n function getPathIn (obj, path, separator) {\n if (isNil(obj)) {\n throw _makeTypeErrorFor(obj, \"object\");\n }\n\n var parts = _toPathParts(path, separator);\n var pathInfo = _getPathInfo(obj, parts, true);\n\n return pathInfo.target;\n }\n\n /**\n * Retrieves the first element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.head([1, 2, 3]) // => 1\n * _.head(\"hello\") // => \"h\"\n * _.head([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.last|last}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var head = getAt(0);\n\n /**\n * Retrieves the last element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.last([1, 2, 3]) // => 3\n * _.last(\"hello\") // => \"o\"\n * _.last([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.head|head}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var last = getAt(-1);\n\n /**\n * Builds a function that creates a copy of an array-like object with the given\n * index changed to the desired value.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.setAt(2, 99)(arr) // => [1, 2, 99, 4, 5]\n * arr // => [1, 2, 3, 4, 5]\n *\n * _.setAt(10, 99)(arr) // => [1, 2, 3, 4, 5] (not a reference to `arr`)\n *\n * @example Using negative indexes\n * _.setAt(-1, 99)(arr) // => [1, 2, 3, 4, 99]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.setIndex|setIndex}\n * @param {Number} index\n * @param {*} value\n * @returns {Function}\n */\n function setAt (index, value) {\n return function (arrayLike) {\n return _setIndex(arrayLike, index, value);\n };\n }\n\n /**\n * Sets the specified key to the given value in a copy of the provided object.
\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.
\n * If the specified key is not part of the source object, it will be added to the\n * result.
\n * The main purpose of the function is to work on simple plain objects used as\n * data structures, such as JSON objects, and makes no effort to play nice with\n * objects created from an OOP perspective (it's not worth it).
\n * For example the prototype of the result will be Object's regardless\n * of the source's one.\n * @example\n * var user = {name: \"John\", surname: \"Doe\", age: 30};\n *\n * _.setIn(user, \"name\", \"Jane\") // => {name: \"Jane\", surname: \"Doe\", age: 30}\n * _.setIn(user, \"gender\", \"male\") // => {name: \"John\", surname: \"Doe\", age: 30, gender: \"male\"}\n *\n * // `user` still is {name: \"John\", surname: \"Doe\", age: 30}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setKey|setKey}\n * @see {@link module:lamb.setPath|setPath}, {@link module:lamb.setPathIn|setPathIn}\n * @param {Object} source\n * @param {String} key\n * @param {*} value\n * @returns {Object}\n */\n function setIn (source, key, value) {\n return _merge(enumerables, source, make([key], [value]));\n }\n\n /**\n * Creates a copy of an array-like object with the given index changed to\n * the desired value.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [1, 2, 3];\n *\n * _.setIndex(arr, 1, 99) // => [1, 99, 3]\n * _.setIndex(arr, -1, 99) // => [1, 2, 99]\n * _.setIndex(arr, 10, 99) // => [1, 2, 3] (not a reference to `arr`)\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.setAt|setAt}\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} value\n * @returns {*}\n */\n var setIndex = aritize(_setIndex, 3);\n\n /**\n * Builds a partial application of {@link module:lamb.setIn|setIn} with the provided\n * key and value.
\n * The resulting function expects the object to act upon.
\n * Please refer to {@link module:lamb.setIn|setIn}'s description for explanations about\n * how the copy of the source object is made.\n * @example\n * var user = {name: \"John\", surname: \"Doe\", age: 30};\n * var setAgeTo40 = _.setKey(\"age\", 40);\n *\n * setAgeTo40(user) // => {name: \"john\", surname: \"doe\", age: 40}\n *\n * // `user` still is {name: \"John\", surname: \"Doe\", age: 30}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setIn|setIn}\n * @see {@link module:lamb.setPath|setPath}, {@link module:lamb.setPathIn|setPathIn}\n * @param {String} key\n * @param {*} value\n * @returns {Function}\n */\n function setKey (key, value) {\n return partial(setIn, _, key, value);\n }\n\n /**\n * Builds a partial application of {@link module:lamb.setPathIn|setPathIn} expecting the\n * object to act upon.
\n * See {@link module:lamb.setPathIn|setPathIn} for more details and examples.\n * @example\n * var user = {id: 1, status: {active: false}};\n * var activate = _.setPath(\"status.active\", true);\n *\n * activate(user) // => {id: 1, status: {active: true}}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setPathIn|setPathIn}\n * @see {@link module:lamb.setIn|setIn}, {@link module:lamb.setKey|setKey}\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\n function setPath (path, value, separator) {\n return partial(setPathIn, _, path, value, separator);\n }\n\n /**\n * Allows to change a nested value in a copy of the provided object.
\n * The function will delegate the \"set action\" to {@link module:lamb.setIn|setIn} or\n * {@link module:lamb.setAt|setAt} depending on the value encountered in the path,\n * so please refer to the documentation of those functions for specifics about the\n * implementation.
\n * Note anyway that the distinction will be between Arrays, delegated\n * to {@link module:lamb.setAt|setAt}, and everything else (including array-like objects),\n * which will be delegated to {@link module:lamb.setIn|setIn}.
\n * As a result of that, array-like objects will be converted to objects having numbers as keys\n * and paths targeting non-object values will be converted to empty objects.
\n * You can anyway target array elements using integers in the path, even negative ones, but\n * the priority will be given to existing, and enumerable, object keys.
\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.
\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * var user = {id: 1, status: {active : false, scores: [2, 4, 6]}};\n *\n * _.setPathIn(user, \"status.active\", true) // => {id: 1, status: {active : true, scores: [2, 4, 6]}}\n *\n * @example Targeting arrays\n * _.setPathIn(user, \"status.scores.0\", 8) // => {id: 1, status: {active : false, scores: [8, 4, 6]}}\n *\n * // you can use negative indexes as well\n * _.setPathIn(user, \"status.scores.-1\", 8) // => {id: 1, status: {active : false, scores: [2, 4, 8]}}\n *\n * @example Arrays can also be part of the path and not necessarily its target\n * var user = {id: 1, scores: [\n * {value: 2, year: \"2000\"},\n * {value: 4, year: \"2001\"},\n * {value: 6, year: \"2002\"}\n * ]};\n *\n * var newUser = _.setPathIn(user, \"scores.0.value\", 8);\n * // \"newUser\" holds:\n * // {id: 1, scores: [\n * // {value: 8, year: \"2000\"},\n * // {value: 4, year: \"2001\"},\n * // {value: 6, year: \"2002\"}\n * // ]}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setPath|setPath}\n * @see {@link module:lamb.setIn|setIn}, {@link module:lamb.setKey|setKey}\n * @param {Object|Array} source\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Object|Array}\n */\n function setPathIn (source, path, value, separator) {\n if (isNil(source)) {\n throw _makeTypeErrorFor(source, \"object\");\n }\n\n return _setPathIn(source, _toPathParts(path, separator), value);\n }\n\n /**\n * Builds a function that creates a copy of an array-like object with the given index\n * changed by applying the provided function to its value.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [\"a\", \"b\", \"c\"];\n * var toUpperCase = _.invoker(\"toUpperCase\");\n *\n * _.updateAt(1, toUpperCase)(arr) // => [\"a\", \"B\", \"c\"]\n * _.updateAt(-1, toUpperCase)(arr) // => [\"a\", \"b\", \"C\"]\n * _.updateAt(10, toUpperCase)(arr) // => [\"a\", \"b\", \"c\"] (not a reference to `arr`)\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.updateIndex|updateIndex}\n * @param {Number} index\n * @param {Function} updater\n * @returns {Function}\n */\n function updateAt (index, updater) {\n return function (arrayLike) {\n return _setIndex(arrayLike, index, null, updater);\n };\n }\n\n /**\n * Creates a copy of the given object having the desired key value updated by applying\n * the provided function to it.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * var user = {name: \"John\", visits: 2};\n * var toUpperCase = _.invoker(\"toUpperCase\");\n *\n * _.updateIn(user, \"name\", toUpperCase) // => {name: \"JOHN\", visits: 2}\n * _.updateIn(user, \"surname\", toUpperCase) // => {name: \"John\", visits: 2}\n *\n * @example Non-enumerable properties will be treated as non-existent:\n * var user = Object.create({name: \"John\"}, {visits: {value: 2}});\n * var increment = _.partial(_.add, 1);\n *\n * _.updateIn(user, \"visits\", increment) // => {name: \"John\", visits: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updateKey|updateKey}\n * @see {@link module:lamb.updatePath|updatePath}, {@link module:lamb.updatePathIn|updatePathIn}\n * @param {Object} source\n * @param {String} key\n * @param {Function} updater\n * @returns {Object}\n */\n function updateIn (source, key, updater) {\n return _isEnumerable(source, key) ? setIn(source, key, updater(source[key])) : _merge(enumerables, source);\n }\n\n /**\n * Creates a copy of an array-like object with the given index changed by applying the\n * provided function to its value.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [\"a\", \"b\", \"c\"];\n * var toUpperCase = _.invoker(\"toUpperCase\");\n *\n * _.updateIndex(arr, 1, toUpperCase) // => [\"a\", \"B\", \"c\"]\n * _.updateIndex(arr, -1, toUpperCase) // => [\"a\", \"b\", \"C\"]\n * _.updateIndex(arr, 10, toUpperCase) // => [\"a\", \"b\", \"c\"] (not a reference to `arr`)\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.updateAt|updateAt}\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {Function} updater\n * @returns {Array}\n */\n var updateIndex = partial(_setIndex, _, _, null, _);\n\n /**\n * Builds a partial application of {@link module:lamb.updateIn|updateIn} with the provided\n * key and updater, expecting the object to act upon.\n * @example\n * var user = {name: \"John\", visits: 2};\n * var increment = _.partial(_.add, 1);\n * var incrementVisits = _.updateKey(\"visits\", increment);\n *\n * incrementVisits(user) // => {name: \"John\", visits: 3}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updateIn|updateIn}\n * @see {@link module:lamb.updatePath|updatePath}, {@link module:lamb.updatePathIn|updatePathIn}\n * @param {String} key\n * @param {Function} updater\n * @returns {Function}\n */\n function updateKey (key, updater) {\n return partial(updateIn, _, key, updater);\n }\n\n /**\n * Builds a partial application of {@link module:lamb.updateIn|updateIn} expecting the object to act upon.\n * @example\n * var user = {id: 1, status: {scores: [2, 4, 6], visits: 0}};\n * var increment = _.partial(_.add, 1);\n * var incrementScores = _.updatePath(\"status.scores\", _.mapWith(increment))\n *\n * incrementScores(user) // => {id: 1, status: {scores: [3, 5, 7], visits: 0}}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updatePathIn|updatePathIn}\n * @see {@link module:lamb.updateIn|updateIn}, {@link module:lamb.updateKey|updateKey}\n * @param {String} path\n * @param {Function} updater\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\n function updatePath (path, updater, separator) {\n return partial(updatePathIn, _, path, updater, separator);\n }\n\n /**\n * Allows to change a nested value in a copy of the given object by applying the provided\n * function to it.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.
\n * @example\n * var user = {id: 1, status: {scores: [2, 4, 6], visits: 0}};\n * var increment = _.partial(_.add, 1);\n *\n * _.updatePathIn(user, \"status.visits\", increment) // => {id: 1, status: {scores: [2, 4, 6]}, visits: 1}\n *\n * @example Targeting arrays\n * _.updatePathIn(user, \"status.scores.0\", increment) // => {id: 1, status: {scores: [3, 4, 6], visits: 0}}\n *\n * // you can use negative indexes as well\n * _.updatePathIn(user, \"status.scores.-1\", increment) // => {id: 1, status: {scores: [2, 4, 7], visits: 0}}\n *\n * @example Arrays can also be part of the path and not necessarily its target\n * var user = {id: 1, scores: [\n * {value: 2, year: \"2000\"},\n * {value: 4, year: \"2001\"},\n * {value: 6, year: \"2002\"}\n * ]};\n *\n * var newUser = _.updatePathIn(user, \"scores.0.value\", increment);\n * // \"newUser\" holds:\n * // {id: 1, scores: [\n * // {value: 3, year: \"2000\"},\n * // {value: 4, year: \"2001\"},\n * // {value: 6, year: \"2002\"}\n * // ]}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updatePath|updatePath}\n * @see {@link module:lamb.updateIn|updateIn}, {@link module:lamb.updateKey|updateKey}\n * @param {Object|Array} source\n * @param {String} path\n * @param {Function} updater\n * @param {String} [separator=\".\"]\n * @returns {Object|Array}\n */\n function updatePathIn (source, path, updater, separator) {\n var parts = _toPathParts(path, separator);\n var pathInfo = _getPathInfo(source, parts, false);\n\n if (pathInfo.isValid) {\n return _setPathIn(source, parts, updater(pathInfo.target));\n } else {\n return Array.isArray(source) ? slice(source) : _merge(enumerables, source);\n }\n }\n\n lamb.getAt = getAt;\n lamb.getIn = getIn;\n lamb.getIndex = getIndex;\n lamb.getKey = getKey;\n lamb.getPath = getPath;\n lamb.getPathIn = getPathIn;\n lamb.head = head;\n lamb.last = last;\n lamb.setAt = setAt;\n lamb.setIn = setIn;\n lamb.setIndex = setIndex;\n lamb.setKey = setKey;\n lamb.setPath = setPath;\n lamb.setPathIn = setPathIn;\n lamb.updateAt = updateAt;\n lamb.updateIn = updateIn;\n lamb.updateIndex = updateIndex;\n lamb.updateKey = updateKey;\n lamb.updatePath = updatePath;\n lamb.updatePathIn = updatePathIn;\n\n\n /**\n * Builds a predicate to check if an array-like object contains the given value.
\n * Please note that the equality test is made with {@link module:lamb.isSVZ|isSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * var containsNaN = _.contains(NaN, 0);\n *\n * containsNaN([0, 1, 2, 3, NaN]) // => true\n *\n * @memberof module:lamb\n * @category Array\n * @param {*} value\n * @param {Number} [fromIndex=0] The position at which to begin searching for the given value.\n * @returns {Function}\n */\n function contains (value, fromIndex) {\n return function (arrayLike) {\n return isIn(arrayLike, value, fromIndex);\n };\n }\n\n /**\n * Returns an array of items present only in the first of the given arrays.
\n * Note that since version 0.13.0 this function uses the [\"SameValueZero\" comparison]{@link module:lamb.isSVZ|isSVZ}.\n * @example\n * var a1 = [1, 2, 3, 4];\n * var a2 = [2, 4, 5];\n * var a3 = [4, 5, 3, 1];\n *\n * _.difference(a1, a2) // => [1, 3]\n * _.difference(a1, a2, a3) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @param {Array} array\n * @param {...Array} other\n * @returns {Array}\n */\n function difference (array) {\n var rest = shallowFlatten(map(slice(arguments, 1), unary(slice)));\n var isInRest = partial(isIn, rest, _, 0);\n return filter(array, not(isInRest));\n }\n\n /**\n * Builds an array without the first n elements of the given array or array-like object.\n * Note that, being this only a shortcut for a specific use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.drop(arr, 2) // => [3, 4, 5]\n * _.drop(arr, -1) // => [5]\n * _.drop(arr, -10) // => [1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {ArrayLike} arrayLike\n * @param {Number} n\n * @returns {Array}\n */\n var drop = binary(slice);\n\n /**\n * A curried version of {@link module:lamb.drop|drop} that expects the number of elements\n * to drop to build a function waiting for the list to take the elements from.\n * See the note and examples for {@link module:lamb.drop|drop} about passing a negative n.\n * @example\n * var drop2 = _.dropN(2);\n *\n * drop2([1, 2, 3, 4, 5]) // => [3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.drop|drop}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {Number} n\n * @returns {Function}\n */\n function dropN (n) {\n return function (arrayLike) {\n return slice(arrayLike, n);\n };\n }\n\n /**\n * Builds a function that drops the first n elements satisfying a predicate from an array or array-like object.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var dropWhileIsEven = _.dropWhile(isEven);\n *\n * dropWhileIsEven([2, 4, 6, 8]) // => []\n * dropWhileIsEven([2, 4, 7, 8]) // => [7, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.takeWhile|takeWhile}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n function dropWhile (predicate, predicateContext) {\n var fn = arguments.length === 2 ? _getNumConsecutiveHits : binary(_getNumConsecutiveHits);\n\n return function (arrayLike) {\n return slice(arrayLike, fn(arrayLike, predicate, predicateContext));\n };\n }\n\n /**\n * Searches for an element satisfying the predicate in the given array-like object and returns it if\n * the search is successful. Returns undefined otherwise.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 40}\n * ];\n *\n * _.find(persons, _.hasKeyValue(\"age\", 40)) // => {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40}\n * _.find(persons, _.hasKeyValue(\"age\", 41)) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {*}\n */\n function find (arrayLike, predicate, predicateContext) {\n var result;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0, len = arrayLike.length, element; i < len; i++) {\n element = arrayLike[i];\n\n if (predicate(element, i, arrayLike)) {\n result = element;\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Searches for an element satisfying the predicate in the given array-like object and returns its\n * index if the search is successful. Returns -1 otherwise.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 40}\n * ];\n *\n * _.findIndex(persons, _.hasKeyValue(\"age\", 40)) // => 1\n * _.findIndex(persons, _.hasKeyValue(\"age\", 41)) // => -1\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Number}\n */\n function findIndex (arrayLike, predicate, predicateContext) {\n var result = -1;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0, len = arrayLike.length; i < len; i++) {\n if (predicate(arrayLike[i], i, arrayLike)) {\n result = i;\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Similar to {@link module:lamb.map|map}, but if the mapping function returns an array this will\n * be concatenated, rather than pushed, to the final result.\n * @example showing the difference with map\n * var words = [\"foo\", \"bar\"];\n * var toCharArray = function (s) { return s.split(\"\"); };\n *\n * _.map(words, toCharArray) // => [[\"f\", \"o\", \"o\"], [\"b\", \"a\", \"r\"]]\n * _.flatMap(words, toCharArray) // => [\"f\", \"o\", \"o\", \"b\", \"a\", \"r\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.flatMapWith|flatMapWith}\n * @param {Array} array\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n var flatMap = compose(shallowFlatten, map);\n\n /**\n * Builds a partial application of {@link module:lamb.flatMap|flatMap} using the given iteratee\n * and the optional context. The resulting function expects the array to act upon.\n * @example\n * var toCharArray = function (s) { return s.split(\"\"); };\n * var wordsToCharArray = _.flatMapWith(toCharArray);\n *\n * wordsToCharArray([\"foo\", \"bar\"]) // => [\"f\", \"o\", \"o\", \"b\", \"a\", \"r\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.flatMap|flatMap}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var flatMapWith = _partialWithIteratee(flatMap);\n\n /**\n * Flattens an array.\n * @example showing the difference with shallowFlatten\n * var arr = [1, 2, [3, 4, [5, 6]], 7, 8];\n *\n * _.flatten(arr) // => [1, 2, 3, 4, 5, 6, 7, 8]\n * _.shallowFlatten(arr) // => [1, 2, 3, 4, [5, 6], 7, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.shallowFlatten|shallowFlatten}\n * @param {Array} array\n * @returns {Array}\n */\n function flatten (array) {\n return Array.isArray(array) ? _flatten(array, []) : slice(array);\n }\n\n /**\n * Returns a copy of the given array-like object without the last element.\n * @example\n * _.init([1, 2, 3, 4]) // => [1, 2, 3]\n * _.init([1]) // => []\n * _.init([]) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.tail|tail}\n * @see {@link module:lamb.head|head}, {@link module:lamb.last|last}\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\n var init = partial(slice, _, 0, -1);\n\n /**\n * Inserts the provided element in a copy of an array-like object at the\n * specified index.
\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.
\n * Negative indexes are allowed; when a negative index is out of bounds\n * the element will be inserted at the start of the resulting array.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.insert(arr, 3, 99) // => [1, 2, 3, 99, 4, 5]\n * _.insert(arr, -2, 99) // => [1, 2, 3, 99, 4, 5]\n * _.insert(arr, 10, 99) // => [1, 2, 3, 4, 5, 99]\n * _.insert(arr, -10, 99) // => [99, 1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.insertAt|insertAt}\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} element\n * @returns {Array}\n */\n function insert (arrayLike, index, element) {\n var result = slice(arrayLike);\n result.splice(index, 0, element);\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.insert|insert}\n * expecting the array-like object to act upon.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.insertAt(3, 99)(arr) // => [1, 2, 3, 99, 4, 5]\n * _.insertAt(-2, 99)(arr) // => [1, 2, 3, 99, 4, 5]\n * _.insertAt(10, 99)(arr) // => [1, 2, 3, 4, 5, 99]\n * _.insertAt(-10, 99)(arr) // => [99, 1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.insert|insert}\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @param {Number} index\n * @param {*} element\n * @returns {Function}\n */\n function insertAt (index, element) {\n return partial(insert, _, index, element);\n }\n\n /**\n * Returns an array of every item present in all given arrays.
\n * Note that since version 0.13.0 this function uses the [\"SameValueZero\" comparison]{@link module:lamb.isSVZ|isSVZ}.\n * @example\n * var a1 = [1, 2, 3, 4];\n * var a2 = [2, 5, 4, 6];\n * var a3 = [5, 6, 7];\n *\n * _.intersection(a1, a2) // => [2, 4]\n * _.intersection(a1, a3) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @param {...Array} array\n * @return {Array}\n */\n function intersection () {\n var rest = slice(arguments, 1);\n\n return filter(uniques(arguments[0]), function (item) {\n return rest.every(contains(item));\n });\n }\n\n /**\n * Checks if an array-like object contains the given value.
\n * Please note that the equality test is made with {@link module:lamb.isSVZ|isSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * var numbers = [0, 1, 2, 3, NaN];\n *\n * _.isIn(numbers, 1) // => true\n * _.isIn(numbers, 0) // => true\n * _.isIn(numbers, -0) // => true\n * _.isIn(numbers, NaN) // => true\n * _.isIn(numbers, 2, 3) // => false\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {*} value\n * @param {Number} [fromIndex=0] The position at which to begin searching for the given value.\n * @returns {Boolean}\n */\n function isIn (arrayLike, value, fromIndex) {\n var result = false;\n\n for (var i = fromIndex >>> 0, len = arrayLike.length; i < len; i++) {\n if (isSVZ(value, arrayLike[i])) {\n result = true;\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Generates an array with the values passed as arguments.\n * @example\n * _.list(1, 2, 3) // => [1, 2, 3]\n *\n * @memberof module:lamb\n * @category Array\n * @param {...*} value\n * @returns {Array}\n */\n function list () {\n var len = arguments.length;\n var result = Array(len);\n\n for (var i = 0; i < len; i++) {\n result[i] = arguments[i];\n }\n\n return result;\n }\n\n /**\n * Splits an array-like object in two lists: the first with the elements satisfying the given predicate,\n * the others with the remaining elements.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n *\n * _.partition(numbers, isEven) // => [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.partitionWith|partitionWith}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Array, Array<*>>}\n */\n function partition (arrayLike, predicate, predicateContext) {\n var result = [[], []];\n var len = arrayLike.length;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0, el; i < len; i++) {\n el = arrayLike[i];\n result[predicate(el, i, arrayLike) ? 0 : 1].push(el);\n }\n\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.partition|partition} using the given predicate and the optional context.\n * The resulting function expects the array-like object to act upon.\n * @example\n * var users = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"active\": false},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"active\": true},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"active\": true},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"active\": false}\n * ];\n * var isActive = _.hasKeyValue(\"active\", true);\n * var splitByActiveStatus = _.partitionWith(isActive);\n *\n * splitByActiveStatus(users) // =>\n * // [[\n * // {\"name\": \"John\", \"surname\": \"Doe\", \"active\": true},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\", \"active\": true}\n * // ], [\n * // {\"name\": \"Jane\", \"surname\": \"Doe\", \"active\": false},\n * // {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"active\": false}\n * // ]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.partition|partition}\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n var partitionWith = _partialWithIteratee(partition);\n\n /**\n * \"Plucks\" the values of the specified key from a list of objects.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 15}\n * ];\n *\n * _.pluck(persons, \"age\") // => [12, 40, 18, 15]\n *\n * var lists = [\n * [1, 2],\n * [3, 4, 5],\n * [6]\n * ];\n *\n * _.pluck(lists, \"length\") // => [2, 3, 1]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.pluckKey|pluckKey}\n * @param {ArrayLike} arrayLike\n * @param {String} key\n * @returns {Array}\n */\n function pluck (arrayLike, key) {\n return map(arrayLike, getKey(key));\n }\n\n /**\n * A curried version of {@link module:lamb.pluck|pluck} expecting the key to retrieve to\n * build a function waiting for the array-like object to act upon.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 15}\n * ];\n * var getAges = _.pluckKey(\"age\");\n *\n * getAges(persons) // => [12, 40, 18, 15]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.pluck|pluck}\n * @function\n * @param {String} key\n * @returns {Function}\n */\n var pluckKey = compose(mapWith, getKey);\n\n /**\n * Reverses a copy of the given array-like object.\n * @example\n * var arr = [1, 2, 3];\n *\n * _.reverse(arr) // => [3, 2, 1];\n *\n * // `arr` still is [1, 2, 3]\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\n function reverse (arrayLike) {\n return slice(arrayLike).reverse();\n }\n\n /**\n * Flattens the \"first level\" of an array.\n * @example showing the difference with flatten\n * var arr = [1, 2, [3, 4, [5, 6]], 7, 8];\n *\n * _.flatten(arr) // => [1, 2, 3, 4, 5, 6, 7, 8]\n * _.shallowFlatten(arr) // => [1, 2, 3, 4, [5, 6], 7, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.flatten|flatten}\n * @param {Array} array\n * @returns {Array}\n */\n function shallowFlatten (array) {\n return Array.isArray(array) ? _arrayProto.concat.apply([], array) : slice(array);\n }\n\n /**\n * Returns a copy of the given array-like object without the first element.\n * @example\n * _.tail([1, 2, 3, 4]) // => [2, 3, 4]\n * _.tail([1]) // => []\n * _.tail([]) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.init|init}\n * @see {@link module:lamb.head|head}, {@link module:lamb.last|last}\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\n var tail = partial(slice, _, 1, void 0);\n\n /**\n * Retrieves the first n elements from an array or array-like object.
\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.take(arr, 3) // => [1, 2, 3]\n * _.take(arr, -1) // => [1, 2, 3, 4]\n * _.take(arr, -10) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {ArrayLike} arrayLike\n * @param {Number} n\n * @returns {Array}\n */\n function take (arrayLike, n) {\n return slice(arrayLike, 0, +n);\n }\n\n /**\n * A curried version of {@link module:lamb.take|take} that expects the number of elements\n * to retrieve to build a function waiting for the list to take the elements from.\n * See the note and examples for {@link module:lamb.take|take} about passing a negative n.\n * @example\n * var take2 = _.takeN(2);\n *\n * take2([1, 2, 3, 4, 5]) // => [1, 2]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.take|take}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {Number} n\n * @returns {Function}\n */\n function takeN (n) {\n return function (arrayLike) {\n return slice(arrayLike, 0, +n);\n };\n }\n\n /**\n * Builds a function that takes the first n elements satisfying a predicate from an array or array-like object.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var takeWhileIsEven = _.takeWhile(isEven);\n *\n * takeWhileIsEven([1, 2, 4, 6, 8]) // => []\n * takeWhileIsEven([2, 4, 7, 8]) // => [2, 4]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @param {ListIteratorCallback} predicate\n * @param {Object} predicateContext\n * @returns {Function}\n */\n function takeWhile (predicate, predicateContext) {\n var fn = arguments.length === 2 ? _getNumConsecutiveHits : binary(_getNumConsecutiveHits);\n\n return function (arrayLike) {\n return slice(arrayLike, 0, fn(arrayLike, predicate, predicateContext));\n };\n }\n\n /**\n * Transposes a matrix. Can also be used to reverse a {@link module:lamb.zip|zip} operation.
\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example transposing a matrix\n * _.transpose([\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ]) // =>\n * // [\n * // [1, 4, 7],\n * // [2, 5, 8],\n * // [3, 6, 9]\n * // ]\n *\n * @example showing the relationship with zip\n * var zipped = _.zip([\"a\", \"b\", \"c\"], [1, 2, 3]); // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\n *\n * _.transpose(zipped) // => [[\"a\", \"b\", \"c\"], [1, 2, 3]]\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike>} arrayLike\n * @returns {Array>}\n */\n function transpose (arrayLike) {\n var result = [];\n var minLen = Math.min.apply(null, pluck(arrayLike, \"length\")) >>> 0;\n var len = arrayLike.length;\n\n for (var i = 0, j; i < minLen; i++) {\n result.push([]);\n\n for (j = 0; j < len; j++) {\n result[i][j] = arrayLike[j][i];\n }\n }\n\n return result;\n }\n\n /**\n * Returns a list of every unique element present in the given array-like objects.\n * @example\n * _.union([1, 2, 3, 2], [3, 4], [1, 5]) // => [1, 2, 3, 4, 5]\n * _.union(\"abc\", \"bcd\", \"cde\") // => [\"a\", \"b\", \"c\", \"d\", \"e\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {...ArrayLike} arrayLike\n * @returns {Array}\n */\n var union = compose(uniques, flatMapWith(unary(slice)), list);\n\n /**\n * Returns an array comprised of the unique elements of the given array-like object.
\n * Can work with lists of complex objects if supplied with an iteratee.
\n * Note that since version 0.13.0 this function uses the [\"SameValueZero\" comparison]{@link module:lamb.isSVZ|isSVZ}.\n * @example with simple values\n * _.uniques([1, 2, 2, 3, 4, 3, 5, 1]) // => [1, 2, 3, 4, 5]\n *\n * @example with complex values\n * var data = [\n * {id: \"1\"},\n * {id: \"4\"},\n * {id: \"5\"},\n * {id: \"1\"},\n * {id: \"5\"},\n * ];\n *\n * _.uniques(data, _.getKey(\"id\")) // => [{id: \"1\"}, {id: \"4\"}, {\"id\": 5}]\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} [iteratee] Defaults to the [identity function]{@link module:lamb.identity}.\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n function uniques (arrayLike, iteratee, iterateeContext) {\n if (typeof iteratee !== \"function\") {\n iteratee = identity;\n }\n\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n var result = [];\n var seen = [];\n var value;\n\n for (var i = 0, len = arrayLike.length; i < len; i++) {\n value = iteratee(arrayLike[i], i, arrayLike);\n\n if (!isIn(seen, value)) {\n seen.push(value);\n result.push(arrayLike[i]);\n }\n }\n\n return result;\n }\n\n /**\n * Builds a list of arrays out of the given array-like objects by pairing items with the same index.
\n * The received array-like objects will be truncated to the shortest length.
\n * See also {@link module:lamb.zipWithIndex|zipWithIndex} and {@link module:lamb.transpose|transpose} for the reverse operation.\n * @example\n * _.zip(\n * [\"a\", \"b\", \"c\"],\n * [1, 2, 3],\n * [true, false, true]\n * ) // => [[\"a\", 1, true], [\"b\", 2, false], [\"c\", 3, true]]\n *\n * _.zip([1, 2, 3, 4], [5, 6, 7]) // => [[1, 5], [2, 6], [3, 7]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {...ArrayLike} arrayLike\n * @returns {Array>}\n */\n var zip = compose(transpose, list);\n\n /**\n * \"{@link module:lamb.zip|Zips}\" an array-like object by pairing its values with their index.\n * @example\n * _.zipWithIndex([\"a\", \"b\", \"c\"]) // => [[\"a\", 0], [\"b\", 1], [\"c\", 2]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {ArrayLike} arrayLike\n * @returns {Array>}\n */\n var zipWithIndex = mapWith(binary(list));\n\n lamb.contains = contains;\n lamb.difference = difference;\n lamb.drop = drop;\n lamb.dropN = dropN;\n lamb.dropWhile = dropWhile;\n lamb.find = find;\n lamb.findIndex = findIndex;\n lamb.flatMap = flatMap;\n lamb.flatMapWith = flatMapWith;\n lamb.flatten = flatten;\n lamb.init = init;\n lamb.insert = insert;\n lamb.insertAt = insertAt;\n lamb.intersection = intersection;\n lamb.isIn = isIn;\n lamb.list = list;\n lamb.partition = partition;\n lamb.partitionWith = partitionWith;\n lamb.pluck = pluck;\n lamb.pluckKey = pluckKey;\n lamb.reverse = reverse;\n lamb.shallowFlatten = shallowFlatten;\n lamb.tail = tail;\n lamb.take = take;\n lamb.takeN = takeN;\n lamb.takeWhile = takeWhile;\n lamb.transpose = transpose;\n lamb.union = union;\n lamb.uniques = uniques;\n lamb.zip = zip;\n lamb.zipWithIndex = zipWithIndex;\n\n\n /**\n * Transforms an array-like object in a lookup table with the keys generated by the provided\n * iteratee, having as values the count of matches for the key.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"age\": 12},\n * {\"name\": \"John\", \"age\": 40},\n * {\"name\": \"Mario\", \"age\": 17},\n * {\"name\": \"Paolo\", \"age\": 15}\n * ];\n * var getAgeStatus = function (person) { return person.age >= 18 ? \"adult\" : \"minor\"; };\n *\n * _.count(persons, getAgeStatus) // => {\"adult\": 1, \"minor\": 3}\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Object}\n */\n var count = _groupWith(partial(add, 1), 0);\n\n /**\n * Using the provided iteratee, and its optional context, builds a partial application of\n * {@link module:lamb.count|count} expecting the array-like object to act upon.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"city\": \"New York\"},\n * {\"name\": \"John\", \"city\": \"New York\"},\n * {\"name\": \"Mario\", \"city\": \"Rome\"},\n * {\"name\": \"Paolo\"}\n * ];\n * var getCityOrUnknown = _.adapter(_.getKey(\"city\"), _.always(\"Unknown\"));\n * var countByCity = _.countBy(getCityOrUnknown);\n *\n * countByCity(persons) // => {\"New York\": 2, \"Rome\": 1, \"Unknown\": 1}\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.count|count}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var countBy = _partialWithIteratee(count);\n\n /**\n * Transforms an array-like object into a lookup table using the provided iteratee as a grouping\n * criterion to generate keys and values.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"city\": \"New York\"},\n * {\"name\": \"John\", \"city\": \"New York\"},\n * {\"name\": \"Mario\", \"city\": \"Rome\"},\n * {\"name\": \"Paolo\"}\n * ];\n * var getCity = _.getKey(\"city\");\n * var personsByCity = _.group(persons, getCity);\n *\n * // \"personsByCity\" holds:\n * // {\n * // \"New York\": [\n * // {\"name\": \"Jane\", \"city\": \"New York\"},\n * // {\"name\": \"John\", \"city\": \"New York\"}\n * // ],\n * // \"Rome\": [\n * // {\"name\": \"Mario\", \"city\": \"Rome\"}\n * // ],\n * // \"undefined\": [\n * // {\"name\": \"Paolo\"}\n * // ]\n * // }\n *\n * @example Adding a custom value for missing keys\n *\n * var getCityOrUnknown = _.adapter(getCity, _.always(\"Unknown\"));\n *\n * var personsByCity = _.group(persons, getCityOrUnknown);\n *\n * // \"personsByCity\" holds:\n * // {\n * // \"New York\": [\n * // {\"name\": \"Jane\", \"city\": \"New York\"},\n * // {\"name\": \"John\", \"city\": \"New York\"}\n * // ],\n * // \"Rome\": [\n * // {\"name\": \"Mario\", \"city\": \"Rome\"}\n * // ],\n * // \"Unknown\": [\n * // {\"name\": \"Paolo\"}\n * // ]\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.groupBy|groupBy}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Object}\n */\n var group = _groupWith(invoker(\"concat\"), []);\n\n /**\n * Using the provided iteratee, and its optional context, builds a partial application\n * of {@link module:lamb.group|group} expecting the array-like object to act upon.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"age\": 12},\n * {\"name\": \"John\", \"age\": 40},\n * {\"name\": \"Mario\", \"age\": 18},\n * {\"name\": \"Paolo\", \"age\": 15}\n * ];\n *\n * var getAgeStatus = function (person) { return person.age > 20 ? \"over 20\" : \"under 20\"; };\n * var groupByAgeStatus = _.groupBy(getAgeStatus);\n *\n * var personsByAgeStatus = groupByAgeStatus(persons);\n *\n * // \"personsByAgeStatus\" holds:\n * // {\n * // \"under 20\": [\n * // {\"name\": \"Jane\", \"age\": 12},\n * // {\"name\": \"Mario\", \"age\": 18},\n * // {\"name\": \"Paolo\", \"age\": 15}\n * // ],\n * // \"over 20\": [\n * // {\"name\": \"John\", \"age\": 40}\n * // ]\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.group|group}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var groupBy = _partialWithIteratee(group);\n\n /**\n * Similar to {@link module:lamb.group|group}, but the generated lookup table will have\n * only one element of the original array-like object for each value.
\n * Should be used only when you're sure that your iteratee won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * var users = [\n * {id: 1, name: \"John\"},\n * {id: 2, name: \"Jane\"},\n * {id: 3, name: \"Mario\"},\n * {id: 4, name: \"John\"}\n * ];\n *\n * var indexedUsers = _.index(users, _.getKey(\"id\"));\n *\n * // \"indexedUsers\" holds:\n * // {\n * // \"1\": {id: 1, name: \"John\"},\n * // \"2\": {id: 2, name: \"Jane\"},\n * // \"3\": {id: 3, name: \"Mario\"},\n * // \"4\": {id: 4, name: \"John\"}\n * // }\n *\n * @example Result of an iteratee producing a duplicate key:\n * var users = [\n * {id: 1, name: \"John\"},\n * {id: 2, name: \"Jane\"},\n * {id: 3, name: \"Mario\"},\n * {id: 4, name: \"John\"}\n * ];\n *\n * var indexedUsers = _.index(users, _.getKey(\"name\"));\n *\n * // \"indexedUsers\" holds:\n * // {\n * // \"John\": {\"id\": 4, \"name\": \"John\"},\n * // \"Jane\": {\"id\": 2, \"name\": \"Jane\"},\n * // \"Mario\": {\"id\": 3, \"name\": \"Mario\"}\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.indexBy|indexBy}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Object}\n */\n var index = _groupWith(getArgAt(1));\n\n /**\n * Using the provided iteratee, and its optional context, builds a partial application\n * of {@link module:lamb.index|index} expecting the array-like object to act upon.\n * @example\n * var users = [\n * {id: 1, name: \"John\"},\n * {id: 2, name: \"Jane\"},\n * {id: 3, name: \"Mario\"}\n * ];\n * var indexByID = _.indexBy(_.getKey(\"id\"));\n *\n * var indexedUsers = indexByID(users);\n *\n * // \"indexedUsers\" holds:\n * // {\n * // \"1\": {id: 1, name: \"John\"},\n * // \"2\": {id: 2, name: \"Jane\"},\n * // \"3\": {id: 3, name: \"Mario\"}\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.index|index}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var indexBy = _partialWithIteratee(index);\n\n lamb.count = count;\n lamb.countBy = countBy;\n lamb.group = group;\n lamb.groupBy = groupBy;\n lamb.index = index;\n lamb.indexBy = indexBy;\n\n\n /**\n * Returns a [stably]{@link https://en.wikipedia.org/wiki/Sorting_algorithm#Stability} sorted copy of an\n * array-like object using the given criteria.
\n * Sorting criteria are built using Lamb's {@link module:lamb.sorter|sorter} function, but you can also\n * pass simple \"reader\" functions and default ascending sorters will be built for you.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in the comparison.
\n * Please note that if the arguments received by the default comparer aren't of the same type, they will be compared as strings.\n *\n * @example Stable sort:\n * var persons = [\n * {\"name\": \"John\", \"surname\" :\"Doe\"},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\"},\n * {\"name\": \"John\", \"surname\" :\"Moe\"},\n * {\"name\": \"Jane\", \"surname\": \"Foe\"}\n * ];\n *\n * var personsByName = _.sort(persons, _.getKey(\"name\"));\n *\n * // personsByName holds:\n * // [\n * // {\"name\": \"Jane\", \"surname\": \"Foe\"},\n * // {\"name\": \"John\", \"surname\" :\"Doe\"},\n * // {\"name\": \"John\", \"surname\" :\"Moe\"},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @example Stable multi-sort:\n * var personsByNameAscSurnameDesc = _.sort(\n * persons,\n * _.getKey(\"name\"),\n * _.sorterDesc(_.getKey(\"surname\"))\n * );\n *\n * // personsByNameAscSurnameDesc holds:\n * // [\n * // {\"name\": \"Jane\", \"surname\": \"Foe\"},\n * // {\"name\": \"John\", \"surname\" :\"Moe\"},\n * // {\"name\": \"John\", \"surname\" :\"Doe\"},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @example Using custom comparers:\n * var localeSorter = new Intl.Collator(\"it\");\n * var chars = [\"a\", \"è\", \"à\", \"é\", \"c\", \"b\", \"e\"];\n *\n * _.sort(chars, localeSorter) // => [\"a\", \"à\", \"b\", \"c\", \"e\", \"é\", \"è\"]\n *\n * var localeSorterDesc = _.sorterDesc(_.identity, localeSorter.compare);\n *\n * _.sort(chars, localeSorterDesc) // => [\"è\", \"é\", \"e\", \"c\", \"b\", \"à\", \"a\"]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @param {ArrayLike} arrayLike\n * @param {...(Sorter|Function)} [sorter={@link module:lamb.sorter|sorter()}]\n * @returns {Array}\n */\n function sort (arrayLike) {\n var criteria = _makeCriteria(slice(arguments, 1));\n var data = [];\n var result = [];\n var len = arrayLike.length;\n\n for (var i = 0; i < len; i++) {\n data.push({\n value: arrayLike[i],\n index: i\n });\n }\n\n data.sort(_compareWith(criteria));\n\n for (i = 0; i < len; i++) {\n result.push(data[i].value);\n }\n\n return result;\n }\n\n /**\n * Inserts an element in a copy of a sorted array respecting the sort order.\n * @example with simple values\n * _.sortedInsert([], 1) // => [1]\n * _.sortedInsert([2, 4, 6], 5) // => [2, 4, 5, 6]\n * _.sortedInsert([4, 2, 1], 3, _.sorterDesc()) // => [4, 3, 2, 1]\n *\n * @example with complex values\n * var persons = [\n * {\"name\": \"jane\", \"surname\": \"doe\"},\n * {\"name\": \"John\", \"surname\": \"Doe\"},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * ];\n *\n * var getLowerCaseName = _.compose(\n * _.invoker(\"toLowerCase\"),\n * _.getKey(\"name\")\n * );\n *\n * var result = _.sortedInsert(\n * persons,\n * {\"name\": \"marco\", \"surname\": \"Rossi\"},\n * getLowerCaseName\n * );\n *\n * // `result` holds:\n * // [\n * // {\"name\": \"jane\", \"surname\": \"doe\"},\n * // {\"name\": \"John\", \"surname\": \"Doe\"},\n * // {\"name\": \"marco\", \"surname\": \"Rossi\"},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @see {@link module:lamb.insert|insert}, {@link module:lamb.insertAt|insertAt} to insert the element at a specific index\n * @param {ArrayLike} arrayLike\n * @param {*} element\n * @param {...(Sorter|Function)} [sorter={@link module:lamb.sorter|sorter()}] - The sorting criteria used to sort the array.\n * @returns {Array}\n */\n function sortedInsert (arrayLike, element) {\n var criteria = _makeCriteria(slice(arguments, 2));\n var result = slice(arrayLike);\n var idx = _getInsertionIndex(result, element, _compareWith(criteria), 0, result.length);\n\n result.splice(idx, 0, element);\n return result;\n }\n\n /**\n * Creates an ascending sort criterion with the provided reader and comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorterDesc|sorterDesc}\n * @param {Function} [reader={@link module:lamb.identity|identity}] A function meant to generate a simple value from a complex one. The function should evaluate the array element and supply the value to be passed to the comparer.\n * @param {Function} [comparer] An optional custom comparer function.\n * @returns {Sorter}\n */\n var sorter = partial(_sorter, _, false, _);\n\n /**\n * Creates a descending sort criterion with the provided reader and comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}\n * @param {Function} [reader={@link module:lamb.identity|identity}] A function meant to generate a simple value from a complex one. The function should evaluate the array element and supply the value to be passed to the comparer.\n * @param {Function} [comparer] An optional custom comparer function.\n * @returns {Sorter}\n */\n var sorterDesc = partial(_sorter, _, true, _);\n\n /**\n * Builds a partial application of {@link module:lamb.sort|sort} using the provided criteria. The returned\n * function expects the array-like object to sort.\n * As usual, sorting criteria are built using Lamb's {@link module:lamb.sorter|sorter} function, but you can also\n * pass simple \"reader\" functions and default ascending sorters will be built.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in the comparison.
\n * See {@link module:lamb.sort|sort} for more examples.\n *\n * @example\n * var sortAsNumbers = _.sortWith(parseFloat);\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * sortAsNumbers(weights) // => [\"1 Kg\", \"2 Kg\", \"7 Kg\", \"10 Kg\"]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sort|sort}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @param {...(Sorter|Function)} [sorter={@link module:lamb.sorter|sorter()}]\n * @returns {Function}\n */\n function sortWith () {\n var sorters = slice(arguments);\n\n return function (arrayLike) {\n return sort.apply(null, [arrayLike].concat(sorters));\n };\n }\n\n lamb.sort = sort;\n lamb.sortedInsert = sortedInsert;\n lamb.sorter = sorter;\n lamb.sorterDesc = sorterDesc;\n lamb.sortWith = sortWith;\n\n\n /**\n * Applies the passed function to the given argument list.\n * @example\n * _.apply(_.add, [3, 4]) // => 7\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {ArrayLike} args\n * @returns {*}\n */\n function apply (fn, args) {\n return fn.apply(this, Object(args));\n }\n\n /**\n * A curried version of {@link module:lamb.apply|apply}. Expects an array-like object to use as arguments\n * and builds a function waiting for the target of the application.\n * @example\n * var data = [3, 4];\n * var applyDataTo = _.applyArgs(data);\n *\n * applyDataTo(_.add) // => 7\n * applyDataTo(_.multiply) // => 12\n *\n * @memberof module:lamb\n * @category Function\n * @param {ArrayLike} args\n * @returns {Function}\n */\n function applyArgs (args) {\n return function (fn) {\n return fn.apply(this, Object(args));\n };\n }\n\n /**\n * Builds a function that passes only the specified amount of arguments to the given function.
\n * As {@link module:lamb.slice|slice} is used to extract the arguments, you can also\n * pass a negative arity.
\n * See also {@link module:lamb.binary|binary} and {@link module:lamb.unary|unary} for common use\n * cases shortcuts.\n * @example\n * function maxArgument () {\n * return Math.max.apply(null, arguments);\n * }\n *\n * maxArgument(10, 11, 45, 99) // => 99\n * _.aritize(maxArgument, 2)(10, 11, 45, 99) // => 11\n *\n * @example Using a negative arity:\n * _.aritize(maxArgument, -1)(10, 11, 45, 99) // => 45\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} arity\n * @returns {Function}\n */\n function aritize (fn, arity) {\n return function () {\n var args = slice(arguments, 0, arity);\n var argsLen = args.length;\n var n = Math.floor(arity);\n\n if (n > 0 && argsLen < n) {\n args = args.concat(Array(n - argsLen));\n }\n\n return fn.apply(this, args);\n };\n }\n\n /**\n * Builds a function that passes only two arguments to the given function.
\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.
\n * See also {@link module:lamb.unary|unary}.\n * @example\n * _.list(1, 2, 3, 4, 5) // => [1, 2, 3, 4, 5]\n * _.binary(_.list)(1, 2, 3, 4, 5) // => [1, 2]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @returns {Function}\n */\n function binary (fn) {\n return function (a, b) {\n return fn.call(this, a, b);\n };\n }\n\n /**\n * Accepts a series of functions and builds a new function. The functions in the series\n * will then be applied, in order, with the values received by the function built with\n * collect.
\n * The collected results will be returned in an array.\n * @example\n * var user = {\n * id: \"jdoe\",\n * name: \"John\",\n * surname: \"Doe\",\n * scores: [2, 4, 7]\n * };\n * var getIDAndLastScore = _.collect(_.getKey(\"id\"), _.getPath(\"scores.-1\"));\n *\n * getIDAndLastScore(user) // => [\"jdoe\", 7]\n *\n * @example\n * var minAndMax = _.collect(Math.min, Math.max);\n *\n * minAndMax(3, 1, -2, 5, 4, -1) // => [-2, 5]\n *\n * @memberof module:lamb\n * @category Function\n * @param {...Function} fn\n * @returns {Function}\n */\n function collect () {\n var functions = slice(arguments);\n\n return function () {\n return map(functions, applyArgs(arguments));\n };\n }\n\n /**\n * Transforms the evaluation of the given function in the evaluation of a sequence of functions\n * expecting only one argument. Each function of the sequence is a partial application of the\n * original one, which will be applied when the specified (or derived) arity is consumed.
\n * Currying will start from the leftmost argument: use {@link module:lamb.curryRight|curryRight}\n * for right currying.
\n * See also {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * and {@link module:lamb.partial|partial}.\n * @example\n * var multiplyBy = _.curry(_.multiply);\n * var multiplyBy10 = multiplyBy(10);\n *\n * multiplyBy10(5) // => 50\n * multiplyBy10(2) // => 20\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curry (fn, arity) {\n return _curry(fn, arity, false);\n }\n\n /**\n * Builds an auto-curried function. The resulting function can be called multiple times with\n * any number of arguments, and the original function will be applied only when the specified\n * (or derived) arity is consumed.
\n * Currying will start from the leftmost argument: use {@link module:lamb.curryableRight|curryableRight}\n * for right currying.
\n * See also {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight} and\n * {@link module:lamb.partial|partial}.\n * @example\n * var collectFourElements = _.curryable(_.list, 4);\n *\n * collectFourElements(2)(3)(4)(5) // => [2, 3, 4, 5]\n * collectFourElements(2)(3, 4)(5) // => [2, 3, 4, 5]\n * collectFourElements(2, 3, 4, 5) // => [2, 3, 4, 5]\n * collectFourElements(2, 3)(4, 5) // => [2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curryable (fn, arity) {\n return _curry(fn, arity, false, true);\n }\n\n /**\n * Same as {@link module:lamb.curryable|curryable}, but currying starts from the rightmost argument.\n * @example\n * var collectFourElements = _.curryableRight(_.list, 4);\n *\n * collectFourElements(2)(3)(4)(5) // => [5, 4, 3, 2]\n * collectFourElements(2)(3, 4)(5) // => [5, 4, 3, 2]\n * collectFourElements(2, 3, 4, 5) // => [5, 4, 3, 2]\n * collectFourElements(2, 3)(4, 5) // => [5, 4, 3, 2]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curryableRight (fn, arity) {\n return _curry(fn, arity, true, true);\n }\n\n /**\n * Same as {@link module:lamb.curry|curry}, but currying starts from the rightmost argument.\n * @example\n * var divideBy = _.curryRight(_.divide);\n * var halve = divideBy(2);\n * halve(3) // => 1.5\n * halve(3, 7) // => 1.5\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curryRight (fn, arity) {\n return _curry(fn, arity, true);\n }\n\n /**\n * Returns a function that will execute the given function only if it stops being called for the specified timespan.
\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call happens immediately.\n * @example A common use case of debounce in a browser environment\n * var updateLayout = function () {\n * // some heavy DOM operations here\n * };\n *\n * window.addEventListener(\"resize\", _.debounce(updateLayout, 200), false);\n *\n * // The resize event is fired repeteadly until the user stops resizing the\n * // window, while the `updateLayout` function is called only once: 200 ms\n * // after he stopped.\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} timespan - Expressed in milliseconds\n * @returns {Function}\n */\n function debounce (fn, timespan) {\n var timeoutID;\n\n return function () {\n var context = this;\n var args = arguments;\n var debounced = function () {\n timeoutID = null;\n fn.apply(context, args);\n };\n\n clearTimeout(timeoutID);\n timeoutID = setTimeout(debounced, timespan);\n };\n }\n\n /**\n * Returns a function that applies its arguments to the original function in reverse order.\n * @example\n * _.list(1, 2, 3) // => [1, 2, 3]\n * _.flip(_.list)(1, 2, 3) // => [3, 2, 1]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @returns {Function}\n */\n function flip (fn) {\n return function () {\n var args = slice(arguments).reverse();\n return fn.apply(this, args);\n };\n }\n\n /**\n * Builds a function that returns the argument received at the given index.
\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.
\n * The resulting function will return undefined if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * var getFirstArg = getArgAt(0);\n * var getLastArg = getArgAt(-1);\n *\n * getFirstArg(1, 2, 3) // => 1\n * getLastArg(1, 2, 3) // => 3\n *\n * getArgAt()(1, 2, 3) // => undefined\n * getArgAt(6)(1, 2, 3) // => undefined\n * getArgAt(1)() // => undefined\n *\n * @memberof module:lamb\n * @category Function\n * @param {Number} index\n * @returns {Function}\n */\n function getArgAt (index) {\n return compose(getAt(index), list);\n }\n\n /**\n * Builds a function that will invoke the given method name on any received object and return\n * the result. If no method with such name is found the function will return undefined.\n * Along with the method name it's possible to supply some arguments that will be bound to the method call.
\n * Further arguments can also be passed when the function is actually called, and they will be concatenated\n * to the bound ones.
\n * If different objects share a method name it's possible to build polymorphic functions as you can see in\n * the example below.
\n * {@link module:lamb.condition|Condition} can be used to wrap invoker to avoid this behaviour\n * by adding a predicate, while {@link module:lamb.adapter|adapter} can build more complex polymorphic functions\n * without the need of homonymy.
\n * Returning undefined or checking for such value is meant to favor composition and interoperability\n * between the aforementioned functions: for a more standard behaviour see also {@link module:lamb.generic|generic}.\n * See also {@link module:lamb.invokerOn|invokerOn}.\n * @example Basic polymorphism with invoker\n * var polySlice = _.invoker(\"slice\");\n *\n * polySlice([1, 2, 3, 4, 5], 1, 3) // => [2, 3]\n * polySlice(\"Hello world\", 1, 3) // => \"el\"\n *\n * @example With bound arguments\n * var substrFrom2 = _.invoker(\"substr\", 2);\n * substrFrom2(\"Hello world\") // => \"llo world\"\n * substrFrom2(\"Hello world\", 5) // => \"llo w\"\n *\n * @memberof module:lamb\n * @category Function\n * @param {String} methodName\n * @param {...*} [boundArg]\n * @returns {Function}\n */\n function invoker (methodName) {\n var boundArgs = slice(arguments, 1);\n return partial(_invoker, boundArgs, methodName);\n }\n\n /**\n * Accepts an object and builds a function expecting a method name, and optionally arguments, to call on such object.\n * Like {@link module:lamb.invoker|invoker}, if no method with the given name is found the function will return undefined.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var arr = [1, 2, 3, 4, 5];\n * var invokerOnArr = _.invokerOn(arr);\n *\n * invokerOnArr(\"filter\", isEven) // => [2, 4]\n * invokerOnArr(\"slice\", 1, 3) // => [2, 3]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.invoker|invoker}\n * @param {Object} target\n * @returns {Function}\n */\n function invokerOn (target) {\n return partial(_invoker, [], _, target);\n }\n\n /**\n * Builds a function that allows to map over the received arguments before applying them to the original one.\n * @example\n * var sumArray = _.reduceWith(_.add);\n * var sum = _.compose(sumArray, _.list);\n *\n * sum(1, 2, 3, 4, 5) // => 15\n *\n * var square = _.partial(Math.pow, _, 2);\n * var sumSquares = _.mapArgs(sum, square);\n *\n * sumSquares(1, 2, 3, 4, 5) // => 55\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {ListIteratorCallback} mapper\n * @returns {Function}\n */\n function mapArgs (fn, mapper) {\n return compose(partial(apply, fn), mapWith(mapper), list);\n }\n\n /**\n * Creates a pipeline of functions, where each function consumes the result of the previous one.
\n * See also {@link module:lamb.compose|compose}.\n * @example\n * var square = _.partial(Math.pow, _, 2);\n * var getMaxAndSquare = _.pipe(Math.max, square);\n *\n * getMaxAndSquare(3, 5) // => 25\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @param {...Function} fn\n * @returns {Function}\n */\n var pipe = flip(compose);\n\n /**\n * Builds a function that allows to \"tap\" into the arguments of the original one.\n * This allows to extract simple values from complex ones, transform arguments or simply intercept them.\n * If a \"tapper\" isn't found the argument is passed as it is.\n * @example\n * var someObject = {count: 5};\n * var someArrayData = [2, 3, 123, 5, 6, 7, 54, 65, 76, 0];\n * var getDataAmount = _.tapArgs(_.add, _.getKey(\"count\"), _.getKey(\"length\"));\n *\n * getDataAmount(someObject, someArrayData); // => 15\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {...?Function} [tapper]\n * @returns {Function}\n */\n function tapArgs (fn) {\n var tappers = slice(arguments, 1);\n\n return function () {\n var len = arguments.length;\n var tappersLen = tappers.length;\n var args = [];\n\n for (var i = 0; i < len; i++) {\n args.push(i < tappersLen ? tappers[i](arguments[i]) : arguments[i]);\n }\n\n return fn.apply(this, args);\n };\n }\n\n /**\n * Returns a function that will invoke the passed function at most once in the given timespan.
\n * The first call in this case happens as soon as the function is invoked; see also {@link module:lamb.debounce|debounce}\n * for a different behaviour where the first call is delayed.\n * @example\n * var log = _.throttle(console.log.bind(console), 5000);\n *\n * log(\"Hi\"); // console logs \"Hi\"\n * log(\"Hi again\"); // nothing happens\n * // after five seconds\n * log(\"Hello world\"); // console logs \"Hello world\"\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} timespan - Expressed in milliseconds.\n * @returns {Function}\n */\n function throttle (fn, timespan) {\n var result;\n var lastCall = 0;\n\n return function () {\n var now = Date.now();\n\n if (now - lastCall >= timespan) {\n lastCall = now;\n result = fn.apply(this, arguments);\n }\n\n return result;\n };\n }\n\n /**\n * Builds a function that passes only one argument to the given function.
\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.
\n * See also {@link module:lamb.binary|binary}.\n * @example\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * weights.map(_.unary(parseInt)) // => [2, 10, 1, 7]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @returns {Function}\n */\n function unary (fn) {\n return function (a) {\n return fn.call(this, a);\n };\n }\n\n /**\n * Wraps the function fn inside a wrapper function.
\n * This allows to conditionally execute fn, to tamper with its arguments or return value\n * and to run code before and after its execution.
\n * Being this nothing more than a \"{@link module:lamb.flip|flipped}\" [partial application]{@link module:lamb.partial},\n * you can also easily build new functions from existent ones.\n * @example\n * var arrayMax = _.wrap(Math.max, _.apply);\n *\n * arrayMax([4, 5, 2, 6, 1]) // => 6\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @param {Function} fn\n * @param {Function} wrapper\n * @returns {Function}\n */\n var wrap = binary(flip(partial));\n\n lamb.apply = apply;\n lamb.applyArgs = applyArgs;\n lamb.aritize = aritize;\n lamb.binary = binary;\n lamb.collect = collect;\n lamb.curry = curry;\n lamb.curryRight = curryRight;\n lamb.curryable = curryable;\n lamb.curryableRight = curryableRight;\n lamb.debounce = debounce;\n lamb.flip = flip;\n lamb.getArgAt = getArgAt;\n lamb.invoker = invoker;\n lamb.invokerOn = invokerOn;\n lamb.mapArgs = mapArgs;\n lamb.pipe = pipe;\n lamb.tapArgs = tapArgs;\n lamb.throttle = throttle;\n lamb.unary = unary;\n lamb.wrap = wrap;\n\n\n /**\n * Builds a checker function meant to be used with {@link module:lamb.validate|validate}.
\n * Note that the function accepts multiple keyPaths as a means to compare their values. In\n * other words all the received keyPaths will be passed as arguments to the predicate\n * to run the test.
\n * If you want to run the same single property check with multiple properties, you should build\n * multiple checkers and combine them with {@link module:lamb.validate|validate}.\n * @example\n * var user = {\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * username: \"jdoe\",\n * password: \"abc123\",\n * passwordConfirm: \"abc123\"\n * }\n * };\n * var pwdMatch = _.checker(\n * _.is,\n * \"Passwords don't match\",\n * [\"login.password\", \"login.passwordConfirm\"]\n * );\n *\n * pwdMatch(user) // => []\n *\n * var newUser = _.setPathIn(user, \"login.passwordConfirm\", \"avc123\");\n *\n * pwdMatch(newUser) // => [\"Passwords don't match\", [\"login.password\", \"login.passwordConfirm\"]]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validate|validate}, {@link module:lamb.validateWith|validateWith}\n * @param {Function} predicate - The predicate to test the object properties\n * @param {String} message - The error message\n * @param {String[]} keyPaths - The array of property names, or {@link module:lamb.getPathIn|paths}, to test.\n * @param {String} [pathSeparator=\".\"]\n * @returns {Array} An error in the form [\"message\", [\"propertyA\", \"propertyB\"]] or an empty array.\n */\n function checker (predicate, message, keyPaths, pathSeparator) {\n return function (obj) {\n var getValues = partial(getPathIn, obj, _, pathSeparator);\n return predicate.apply(obj, map(keyPaths, getValues)) ? [] : [message, keyPaths];\n };\n }\n\n /**\n * Creates an array with all the enumerable properties of the given object.\n * @example Showing the difference with {@link module:lamb.keys|keys}\n * var baseFoo = Object.create({a: 1}, {b: {value: 2}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3},\n * d: {value: 4, enumerable: true}\n * });\n *\n * _.keys(foo) // => [\"d\"]\n * _.enumerables(foo) // => [\"d\", \"a\"]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.keys|keys}\n * @param {Object} obj\n * @returns {String[]}\n */\n var enumerables = _unsafeKeyListFrom(_safeEnumerables);\n\n /**\n * Builds an object from a list of key / value pairs like the one\n * returned by [pairs]{@link module:lamb.pairs} or {@link module:lamb.ownPairs|ownPairs}.
\n * In case of duplicate keys the last key / value pair is used.\n * @example\n * _.fromPairs([[\"a\", 1], [\"b\", 2], [\"c\", 3]]) // => {\"a\": 1, \"b\": 2, \"c\": 3}\n * _.fromPairs([[\"a\", 1], [\"b\", 2], [\"a\", 3]]) // => {\"a\": 3, \"b\": 2}\n * _.fromPairs([[1], [void 0, 2], [null, 3]]) // => {\"1\": undefined, \"undefined\": 2, \"null\": 3}\n *\n * @memberof module:lamb\n * @category Object\n * @param {Array>} pairsList\n * @returns {Object}\n */\n function fromPairs (pairsList) {\n var result = {};\n\n forEach(pairsList, function (pair) {\n result[pair[0]] = pair[1];\n });\n\n return result;\n }\n\n /**\n * Verifies the existence of a property in an object.\n * @example\n * var user1 = {name: \"john\"};\n *\n * _.has(user1, \"name\") // => true\n * _.has(user1, \"surname\") // => false\n * _.has(user1, \"toString\") // => true\n *\n * var user2 = Object.create(null);\n *\n * // not inherited through the prototype chain\n * _.has(user2, \"toString\") // => false\n *\n * @memberof module:lamb\n * @category Object\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n function has (obj, key) {\n if (typeof obj !== \"object\" && !isUndefined(obj)) {\n obj = Object(obj);\n }\n\n return key in obj;\n }\n\n /**\n * Curried version of {@link module:lamb.has|has}.
\n * Returns a function expecting the object to check against the given key.\n * @example\n * var user1 = {name: \"john\"};\n * var user2 = {};\n * var hasName = _.hasKey(\"name\");\n *\n * hasName(user1) // => true\n * hasName(user2) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @param {String} key\n * @returns {Function}\n */\n function hasKey (key) {\n return function (obj) {\n return has(obj, key);\n };\n }\n\n /**\n * Builds a function expecting an object to check against the given key / value pair.\n * @example\n * var hasTheCorrectAnswer = _.hasKeyValue(\"answer\", 42);\n *\n * hasTheCorrectAnswer({answer: 2}) // false\n * hasTheCorrectAnswer({answer: 42}) // true\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {String} key\n * @param {*} value\n * @returns {Function}\n */\n var hasKeyValue = function (key, value) {\n return compose(partial(is, value), getKey(key));\n };\n\n /**\n * Verifies if an object has the specified property and that the property isn't inherited through\n * the prototype chain.
\n * @example Comparison with has.\n * var user = {name: \"john\"};\n *\n * _.has(user, \"name\") // => true\n * _.has(user, \"surname\") // => false\n * _.has(user, \"toString\") // => true\n *\n * _.hasOwn(user, \"name\") // => true\n * _.hasOwn(user, \"surname\") // => false\n * _.hasOwn(user, \"toString\") // => false\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n var hasOwn = generic(_objectProto.hasOwnProperty);\n\n /**\n * Curried version of {@link module:lamb.hasOwn|hasOwn}.
\n * Returns a function expecting the object to check against the given key.\n * @example\n * var user = {name: \"john\"};\n * var hasOwnName = _.hasOwnKey(\"name\");\n * var hasOwnToString = _.hasOwnToString(\"toString\");\n *\n * hasOwnName(user) // => true\n * hasOwnToString(user) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @param {String} key\n * @returns {Function}\n */\n function hasOwnKey (key) {\n return function (obj) {\n return hasOwn(obj, key);\n };\n }\n\n /**\n * Makes an object immutable by recursively calling [Object.freeze]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze}\n * on its members.
\n * Any attempt to extend or modify the object can throw a TypeError or fail silently,\n * depending on the environment and the [strict mode]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode} directive.\n * @example\n * var user = _.immutable({\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * username: \"jdoe\",\n * password: \"abc123\"\n * },\n * luckyNumbers: [13, 17]\n * });\n *\n * // All of these statements will fail and possibly\n * // throw a TypeError (see the function description)\n * user.name = \"Joe\";\n * delete user.name;\n * user.newProperty = [];\n * user.login.password = \"foo\";\n * user.luckyNumbers.push(-13);\n *\n * @memberof module:lamb\n * @category Object\n * @param {Object} obj\n * @returns {Object}\n */\n function immutable (obj) {\n return _immutable(obj, []);\n }\n\n /**\n * Retrieves the list of the own enumerable properties of an object.
\n * Although [Object.keys]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys}\n * is already present in ECMAScript 5, its behaviour changed in the subsequent specifications\n * of the standard as you can read in the link above.
\n * This function shims the ECMAScript 6 version, by forcing a conversion to\n * object for any value but null and undefined.\n * @example Showing the difference with {@link module:lamb.enumerables|enumerables}\n * var baseFoo = Object.create({a: 1}, {b: {value: 2}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3},\n * d: {value: 4, enumerable: true}\n * });\n *\n * _.enumerables(foo) // => [\"d\", \"a\"]\n * _.keys(foo) // => [\"d\"]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.enumerables|enumerables}\n * @param {Object} obj\n * @returns {String[]}\n */\n var keys = _unsafeKeyListFrom(_safeKeys);\n\n /**\n * Builds an object from the two given lists, using the first one as keys and the last one as values.
\n * If the list of keys is longer than the values one, the keys will be created with undefined values.
\n * If more values than keys are supplied, the extra values will be ignored.
\n * See also {@link module:lamb.tear|tear} and {@link module:lamb.tearOwn|tearOwn} for the reverse operation.\n * @example\n * _.make([\"a\", \"b\", \"c\"], [1, 2, 3]) // => {a: 1, b: 2, c: 3}\n * _.make([\"a\", \"b\", \"c\"], [1, 2]) // => {a: 1, b: 2, c: undefined}\n * _.make([\"a\", \"b\"], [1, 2, 3]) // => {a: 1, b: 2}\n * _.make([null, void 0, 2], [1, 2, 3]) // => {\"null\": 1, \"undefined\": 2, \"2\": 3}\n *\n * @memberof module:lamb\n * @category Object\n * @param {String[]} keys\n * @param {ArrayLike} values\n * @returns {Object}\n */\n function make (keys, values) {\n var result = {};\n var valuesLen = values.length;\n\n for (var i = 0, len = keys.length; i < len; i++) {\n result[keys[i]] = i < valuesLen ? values[i] : void 0;\n }\n\n return result;\n }\n\n /**\n * Merges the enumerable properties of the provided sources into a new object.
\n * In case of key homonymy each source has precedence over the previous one.
\n * See also {@link module:lamb.mergeOwn|mergeOwn} for merging only own properties of\n * the given sources.\n * @example\n * _.merge({a: 1}, {b: 3, c: 4}, {b: 5}) // => {a: 1, b: 5, c: 4}\n *\n * @example Arrays and array-like objects will be transformed to objects with numbers as keys:\n * _.merge([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.merge(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other value will be treated as an empty object:\n * _.merge({a: 2}, null, NaN) // => {a: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {...Object} source\n * @returns {Object}\n */\n var merge = partial(_merge, _safeEnumerables);\n\n /**\n * Same as {@link module:lamb.merge|merge}, but only the own properties of the sources are taken into account.\n * @example showing the difference with merge:\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * var bar = {d: 4};\n *\n * _.merge(foo, bar) // => {a: 1, b: 2, c: 3, d: 4}\n * _.mergeOwn(foo, bar) // => {c: 3, d: 4}\n *\n * @example Arrays or array-like objects will be transformed to objects with numbers as keys:\n * _.mergeOwn([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.mergeOwn(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other value will be treated as an empty object:\n * _.mergeOwn({a: 2}, null, NaN) // => {a: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {...Object} source\n * @returns {Object}\n */\n var mergeOwn = partial(_merge, _safeKeys);\n\n /**\n * Same as {@link module:lamb.pairs|pairs}, but only the own enumerable properties of the object are\n * taken into account.
\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example showing the difference with pairs\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * _.pairs(foo) // => [[\"c\", 3], [\"b\", 2], [\"a\", 1]]\n * _.ownPairs(foo) // => [[\"c\", 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array>}\n */\n var ownPairs = _pairsFrom(keys);\n\n /**\n * Same as {@link module:lamb.values|values}, but only the own enumerable properties of the object are\n * taken into account.
\n * @example showing the difference with values\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * _.values(foo) // => [3, 2, 1]\n * _.ownValues(foo) // => [3]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array}\n */\n var ownValues = _valuesFrom(keys);\n\n /**\n * Converts an object into an array of key / value pairs of its enumerable properties.
\n * See also {@link module:lamb.ownPairs|ownPairs} for picking only the own enumerable\n * properties and {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example\n * _.pairs({a: 1, b: 2, c: 3}) // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array>}\n */\n var pairs = _pairsFrom(enumerables);\n\n /**\n * Returns an object containing only the specified properties of the given object.
\n * Non existent properties will be ignored.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.pick(user, [\"name\", \"age\"]) // => {\"name\": \"john\", \"age\": 30};\n * _.pick(user, [\"name\", \"email\"]) // => {\"name\": \"john\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pickIf|pickIf}, {@link module:lamb.pickKeys|pickKeys}\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipIf|skipIf}\n * @param {Object} source\n * @param {String[]} whitelist\n * @returns {Object}\n */\n function pick (source, whitelist) {\n var result = {};\n\n forEach(whitelist, function (key) {\n if (has(source, key)) {\n result[key] = source[key];\n }\n });\n\n return result;\n }\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked against the given predicate.
\n * The properties satisfying the predicate will be included in the resulting object.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n * var pickIfIsString = _.pickIf(_.isType(\"String\"));\n *\n * pickIfIsString(user) // => {name: \"john\", surname: \"doe\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipKeys|skipKeys}, {@link module:lamb.skipIf|skipIf}\n * @param {ObjectIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n function pickIf (predicate, predicateContext) {\n if (arguments.length === 2) {\n predicate = predicate.bind(predicateContext);\n }\n\n return function (source) {\n var result = {};\n\n forEach(enumerables(source), function (key) {\n if (predicate(source[key], key, source)) {\n result[key] = source[key];\n }\n });\n\n return result;\n };\n }\n\n /**\n * A curried version of {@link module:lamb.pick|pick}, expecting a whitelist of keys to build\n * a function waiting for the object to act upon.\n * @example\n * var user = {id: 1, name: \"Jane\", surname: \"Doe\", active: false};\n * var getUserInfo = _.pickKeys([\"id\", \"active\"]);\n *\n * getUserInfo(user) // => {id: 1, active: false}\n *\n * @example A useful composition with mapWith:\n * var users = [\n * {id: 1, name: \"Jane\", surname: \"Doe\", active: false},\n * {id: 2, name: \"John\", surname: \"Doe\", active: true},\n * {id: 3, name: \"Mario\", surname: \"Rossi\", active: true},\n * {id: 4, name: \"Paolo\", surname: \"Bianchi\", active: false}\n * ];\n * var select = _.compose(_.mapWith, _.pickKeys);\n * var selectUserInfo = select([\"id\", \"active\"]);\n *\n * selectUserInfo(users) // =>\n * // [\n * // {id: 1, active: false},\n * // {id: 2, active: true},\n * // {id: 3, active: true},\n * // {id: 4, active: false}\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickIf|pickIf}\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipKeys|skipKeys}, {@link module:lamb.skipIf|skipIf}\n * @param {String[]} whitelist\n * @returns {Function}\n */\n var pickKeys = _curry(pick, 2, true);\n\n /**\n * Creates a copy of the given object with its enumerable keys renamed as\n * indicated in the provided lookup table.\n * @example\n * var person = {\"firstName\": \"John\", \"lastName\": \"Doe\"};\n * var keysMap = {\"firstName\": \"name\", \"lastName\": \"surname\"};\n *\n * _.rename(person, keysMap) // => {\"name\": \"John\", \"surname\": \"Doe\"}\n *\n * @example It's safe using it to swap keys:\n * var keysMap = {\"firstName\": \"lastName\", \"lastName\": \"firstName\"};\n *\n * _.rename(person, keysMap) // => {\"lastName\": \"John\", \"firstName\": \"Doe\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.renameKeys|renameKeys}, {@link module:lamb.renameWith|renameWith}\n * @param {Object} source\n * @param {Object} keysMap\n * @returns {Object}\n */\n function rename (source, keysMap) {\n keysMap = Object(keysMap);\n var result = {};\n var oldKeys = enumerables(source);\n\n for (var prop in keysMap) {\n if (~oldKeys.indexOf(prop)) {\n result[keysMap[prop]] = source[prop];\n }\n }\n\n for (var i = 0, len = oldKeys.length, key; i < len; i++) {\n key = oldKeys[i];\n\n if (!(key in keysMap || key in result)) {\n result[key] = source[key];\n }\n }\n\n return result;\n }\n\n /**\n * A curried version of {@link module:lamb.rename|rename} expecting a\n * keysMap to build a function waiting for the object to act upon.\n * @example\n * var persons = [\n * {\"firstName\": \"John\", \"lastName\": \"Doe\"},\n * {\"first_name\": \"Mario\", \"last_name\": \"Rossi\"},\n * ];\n * var normalizeKeys = _.renameKeys({\n * \"firstName\": \"name\",\n * \"first_name\": \"name\",\n * \"lastName\": \"surname\",\n * \"last_name\": \"surname\"\n * });\n *\n * persons.map(normalizeKeys) // => [{\"name\": \"John\", \"surname\": \"Doe\"}, {\"name\": \"Mario\", \"surname\": \"Rossi\"}]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.rename|rename}, {@link module:lamb.renameWith|renameWith}\n * @param {Object} keysMap\n * @returns {Function}\n */\n var renameKeys = _curry(rename, 2, true);\n\n /**\n * Uses the provided function as a keysMap generator and returns\n * a function expecting the object whose keys we want to {@link module:lamb.rename|rename}.\n * @example\n * var person = {\"NAME\": \"John\", \"SURNAME\": \"Doe\"};\n * var makeLowerKeysMap = function (source) {\n * var sourceKeys = _.keys(source);\n * return _.make(sourceKeys, sourceKeys.map(_.invoker(\"toLowerCase\")));\n * };\n * var lowerKeysFor = _.renameWith(makeLowerKeysMap);\n *\n * lowerKeysFor(person) // => {\"name\": \"John\", \"surname\": \"doe\"};\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.rename|rename}, {@link module:lamb.renameKeys|renameKeys}\n * @param {Function} fn\n * @returns {Function}\n */\n function renameWith (fn) {\n return function (source) {\n return rename(source, fn(source));\n };\n }\n\n /**\n * Returns a copy of the source object without the specified properties.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.skip(user, [\"name\", \"age\"]) // => {surname: \"doe\"};\n * _.skip(user, [\"name\", \"email\"]) // => {surname: \"doe\", age: 30};\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.skipKeys|skipKeys}, {@link module:lamb.skipIf|skipIf}\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}, {@link module:lamb.pickIf|pickIf}\n * @param {Object} source\n * @param {String[]} blacklist\n * @returns {Object}\n */\n function skip (source, blacklist) {\n var result = {};\n\n forEach(enumerables(source), function (key) {\n if (!isIn(blacklist, key)) {\n result[key] = source[key];\n }\n });\n\n return result;\n }\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked against the given predicate.
\n * The properties satisfying the predicate will be omitted in the resulting object.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n * var skipIfIstring = _.skipIf(_.isType(\"String\"));\n *\n * skipIfIstring(user) // => {age: 30}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipKeys|skipKeys}\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}, {@link module:lamb.pickIf|pickIf}\n * @param {ObjectIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n var skipIf = tapArgs(pickIf, not);\n\n /**\n * A curried version of {@link module:lamb.skip|skip}, expecting a blacklist of keys to build\n * a function waiting for the object to act upon.\n * @example\n * var user = {id: 1, name: \"Jane\", surname: \"Doe\", active: false};\n * var getUserInfo = _.skipKeys([\"name\", \"surname\"]);\n *\n * getUserInfo(user) // => {id: 1, active: false}\n *\n * @example A useful composition with mapWith:\n * var users = [\n * {id: 1, name: \"Jane\", surname: \"Doe\", active: false},\n * {id: 2, name: \"John\", surname: \"Doe\", active: true},\n * {id: 3, name: \"Mario\", surname: \"Rossi\", active: true},\n * {id: 4, name: \"Paolo\", surname: \"Bianchi\", active: false}\n * ];\n * var discard = _.compose(_.mapWith, _.skipKeys);\n * var discardNames = discard([\"name\", \"surname\"]);\n *\n * discardNames(users) // =>\n * // [\n * // {id: 1, active: false},\n * // {id: 2, active: true},\n * // {id: 3, active: true},\n * // {id: 4, active: false}\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipIf|skipIf}\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}, {@link module:lamb.pickIf|pickIf}\n * @param {String[]} blacklist\n * @returns {Function}\n */\n var skipKeys = _curry(skip, 2, true);\n\n /**\n * Tears an object apart by transforming it in an array of two lists: one containing its enumerable keys,\n * the other containing the corresponding values.
\n * Although this \"tearing apart\" may sound as a rather violent process, the source object will be unharmed.
\n * See also {@link module:lamb.tearOwn|tearOwn} for picking only the own enumerable properties and\n * {@link module:lamb.make|make} for the reverse operation.\n * @example\n * _.tear({a: 1, b: 2, c: 3}) // => [[\"a\", \"b\", \"c\"], [1, 2, 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array, Array<*>>}\n */\n var tear = _tearFrom(enumerables);\n\n /**\n * Same as {@link module:lamb.tear|tear}, but only the own properties of the object are taken into account.
\n * See also {@link module:lamb.make|make} for the reverse operation.\n * @example showing the difference with tear\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * _.tear(foo) // => [[\"c\", \"b\", \"a\"], [3, 2, 1]]\n * _.tearOwn(foo) // => [[\"c\"], [3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array, Array<*>>}\n */\n var tearOwn = _tearFrom(keys);\n\n /**\n * Validates an object with the given list of {@link module:lamb.checker|checker} functions.\n * @example\n * var hasContent = function (s) { return s.trim().length > 0; };\n * var isAdult = function (age) { return age >= 18; };\n * var userCheckers = [\n * _.checker(hasContent, \"Name is required\", [\"name\"]),\n * _.checker(hasContent, \"Surname is required\", [\"surname\"]),\n * _.checker(isAdult, \"Must be at least 18 years old\", [\"age\"])\n * ];\n *\n * var user1 = {name: \"john\", surname: \"doe\", age: 30};\n * var user2 = {name: \"jane\", surname: \"\", age: 15};\n *\n * _.validate(user1, userCheckers) // => []\n * _.validate(user2, userCheckers) // => [[\"Surname is required\", [\"surname\"]], [\"Must be at least 18 years old\", [\"age\"]]]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validateWith|validateWith}\n * @see {@link module:lamb.checker|checker}\n * @param {Object} obj\n * @param {Function[]} checkers\n * @returns {Array>} An array of errors in the form returned by {@link module:lamb.checker|checker}, or an empty array.\n */\n function validate (obj, checkers) {\n return reduce(checkers, function (errors, checker) {\n var result = checker(obj);\n result.length && errors.push(result);\n return errors;\n }, []);\n }\n\n /**\n * A curried version of {@link module:lamb.validate|validate} accepting a list of {@link module:lamb.checker|checkers} and\n * returning a function expecting the object to validate.\n * @example\n * var hasContent = function (s) { return s.trim().length > 0; };\n * var isAdult = function (age) { return age >= 18; };\n * var userCheckers = [\n * _.checker(hasContent, \"Name is required\", [\"name\"]),\n * _.checker(hasContent, \"Surname is required\", [\"surname\"]),\n * _.checker(isAdult, \"Must be at least 18 years old\", [\"age\"])\n * ];\n * var validateUser = _.validateWith(userCheckers);\n *\n * var user1 = {name: \"john\", surname: \"doe\", age: 30};\n * var user2 = {name: \"jane\", surname: \"\", age: 15};\n *\n * validateUser(user1) // => []\n * validateUser(user2) // => [[\"Surname is required\", [\"surname\"]], [\"Must be at least 18 years old\", [\"age\"]]]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validate|validate}\n * @see {@link module:lamb.checker|checker}\n * @function\n * @param {Function[]} checkers\n * @returns {Function}\n */\n var validateWith = _curry(validate, 2, true);\n\n /**\n * Generates an array with the values of the enumerable properties of the given object.
\n * See also {@link module:lamb.ownValues|ownValues} for picking only the own properties of the object.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.values(user) // => [\"john\", \"doe\", 30]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array}\n */\n var values = _valuesFrom(enumerables);\n\n lamb.checker = checker;\n lamb.enumerables = enumerables;\n lamb.fromPairs = fromPairs;\n lamb.has = has;\n lamb.hasKey = hasKey;\n lamb.hasKeyValue = hasKeyValue;\n lamb.hasOwn = hasOwn;\n lamb.hasOwnKey = hasOwnKey;\n lamb.immutable = immutable;\n lamb.keys = keys;\n lamb.make = make;\n lamb.merge = merge;\n lamb.mergeOwn = mergeOwn;\n lamb.ownPairs = ownPairs;\n lamb.ownValues = ownValues;\n lamb.pairs = pairs;\n lamb.pick = pick;\n lamb.pickIf = pickIf;\n lamb.pickKeys = pickKeys;\n lamb.rename = rename;\n lamb.renameKeys = renameKeys;\n lamb.renameWith = renameWith;\n lamb.skip = skip;\n lamb.skipIf = skipIf;\n lamb.skipKeys = skipKeys;\n lamb.tear = tear;\n lamb.tearOwn = tearOwn;\n lamb.validate = validate;\n lamb.validateWith = validateWith;\n lamb.values = values;\n\n\n /**\n * Pads a string to the desired length with the given char starting from the beginning of the string.\n * @example\n * _.padLeft(\"foo\", \"-\", 0) // => \"foo\"\n * _.padLeft(\"foo\", \"-\", -1) // => \"foo\"\n * _.padLeft(\"foo\", \"-\", 5) // => \"--foo\"\n * _.padLeft(\"foo\", \"-\", 3) // => \"foo\"\n * _.padLeft(\"foo\", \"ab\", 7) // => \"aaaafoo\"\n * _.padLeft(\"foo\", \"\", 5) // => \" foo\"\n * _.padLeft(\"\", \"-\", 5) // => \"-----\"\n *\n * @memberof module:lamb\n * @category String\n * @param {String} source\n * @param {String} [char=\" \"] - The padding char. If a string is passed only the first char is used.\n * @param {Number} len\n * @returns {String}\n */\n function padLeft (source, char, len) {\n return _getPadding(source, char, len) + source;\n }\n\n /**\n * Pads a string to the desired length with the given char starting from the end of the string.\n * @example\n * _.padRight(\"foo\", \"-\", 0) // => \"foo\"\n * _.padRight(\"foo\", \"-\", -1) // => \"foo\"\n * _.padRight(\"foo\", \"-\", 5) // => \"foo--\"\n * _.padRight(\"foo\", \"-\", 3) // => \"foo\"\n * _.padRight(\"foo\", \"ab\", 7) // => \"fooaaaa\"\n * _.padRight(\"foo\", \"\", 5) // => \"foo \"\n * _.padRight(\"\", \"-\", 5) // => \"-----\"\n *\n * @memberof module:lamb\n * @category String\n * @param {String} source\n * @param {String} [char=\" \"] - The padding char. If a string is passed only the first char is used.\n * @param {Number} len\n * @returns {String}\n */\n function padRight (source, char, len) {\n return source + _getPadding(source, char, len);\n }\n\n /**\n * Builds a new string by repeating the source string the desired amount of times.
\n * Note that unlike the current ES6 proposal for [String.prototype.repeat]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat},\n * this function doesn't throw a RangeError if count is negative, but returns an empty string instead.\n * @example\n * _.repeat(\"Hello\", -1) // => \"\"\n * _.repeat(\"Hello\", 1) // => \"Hello\"\n * _.repeat(\"Hello\", 3) // => \"HelloHelloHello\"\n *\n * @memberof module:lamb\n * @category String\n * @param {String} source\n * @param {Number} count\n * @returns {String}\n */\n function repeat (source, count) {\n var result = \"\";\n\n for (var i = 0; i < count; i++) {\n result += source;\n }\n\n return result;\n }\n\n /**\n * Builds a predicate expecting a string to test against the given regular expression pattern.\n * @example\n * var hasNumbersOnly = _.testWith(/^\\d+$/);\n *\n * hasNumbersOnly(\"123\") // => true\n * hasNumbersOnly(\"123 Kg\") // => false\n *\n * @memberof module:lamb\n * @category String\n * @param {RegExp} pattern\n * @returns {Function}\n */\n function testWith (pattern) {\n return _reProto.test.bind(pattern);\n }\n\n lamb.padLeft = padLeft;\n lamb.padRight = padRight;\n lamb.repeat = repeat;\n lamb.testWith = testWith;\n\n /* istanbul ignore next */\n if (typeof exports === \"object\") {\n module.exports = lamb;\n } else if (typeof define === \"function\" && define.amd) {\n define(function() { return lamb; });\n } else {\n host.lamb = lamb;\n }\n}(this);\n\n/**\n * @callback AccumulatorCallback\n * @global\n * @param {*} previousValue The value returned it the last execution of the accumulator or, in the first iteration, the {@link module:lamb.reduce|initialValue} if supplied.\n * @param {*} currentValue The value being processed in the current iteration.\n * @param {Number} idx - The index of the element being processed.\n * @param {ArrayLike} arrayLike - The list being traversed.\n */\n\n/**\n * The built-in arguments object.\n * @typedef {arguments} arguments\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments|arguments} in Mozilla documentation.\n */\n\n/**\n * The built-in Array object.\n * @typedef {Array} Array\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array|Array} in Mozilla documentation.\n */\n\n/**\n * Any array-like object.\n * @typedef {Array|String|arguments|?} ArrayLike\n * @global\n */\n\n/**\n * The built-in Boolean object.\n * @typedef {Boolean} Boolean\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean|Boolean} in Mozilla documentation.\n */\n\n/**\n * The built-in Date object.\n * @typedef {Date} Date\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date|Date} in Mozilla documentation.\n */\n\n/**\n * The built-in Function object.\n * @typedef {Function} function\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function|Function} and\n * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions|Functions} in Mozilla documentation.\n */\n\n/**\n * @callback ListIteratorCallback\n * @global\n * @param {*} element - The element being evaluated.\n * @param {Number} idx - The index of the element within the list.\n * @param {ArrayLike} arrayLike - The list being traversed.\n */\n\n/**\n * The built-in Number object.\n * @typedef {Number} Number\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number|Number} in Mozilla documentation.\n */\n\n/**\n * The built-in Object object.\n * @typedef {Object} Object\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object|Object} in Mozilla documentation.\n */\n\n/**\n * @callback ObjectIteratorCallback\n * @global\n * @param {*} value - The value of the current property.\n * @param {String} key - The property name.\n * @param {Object} source - The object being traversed.\n */\n\n/**\n * The built-in RegExp object.\n * @typedef {RegExp} RegExp\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp|RegExp} in Mozilla documentation.\n */\n\n/**\n * Represent a sorting criteria used by {@link module:lamb.sortedInsert|sortedInsert}, {@link module:lamb.sort|sort} and {@link module:lamb.sortWith|sortWith},\n * and it's usually built using {@link module:lamb.sorter|sorter} and {@link module:lamb.sorterDesc|sorterDesc}.\n * @typedef {Sorter} Sorter\n * @global\n * @property {Boolean} isDescending\n * @property {Function} compare\n */\n\n/**\n * The built-in String object.\n * @typedef {String} String\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String|String} in Mozilla documentation.\n */\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["lamb.js"],"names":["host","always","value","compose","functions","arguments","args","len","length","apply","this","identity","partial","fn","slice","boundArg","lastArgumentIdx","newArgs","argsLen","i","_","_comparer","a","b","result","String","isSVZ","_compareWith","criteria","isDescSort","criterion","compare","isDescending","index","_currier","arity","isRightCurry","slicer","argsHolder","concat","reverse","_curry","isAutoCurry","argsObj","_flatten","array","output","forEach","Array","isArray","push","_getInsertionIndex","element","comparer","start","end","pivot","_getNaturalIndex","target","_isInteger","clamp","_getNumConsecutiveHits","arrayLike","predicate","predicateContext","idx","bind","_getPadding","source","char","isNil","type","repeat","Object","Math","ceil","_getPathInfo","obj","parts","walkNonEnumerables","key","keyAsNumber","_isEnumerable","Number","isUndefined","isValid","_groupWith","makeValue","startValue","iteratee","iterateeContext","reduce","_immutable","seen","indexOf","freeze","getOwnPropertyNames","isNull","_invoker","boundArgs","methodName","method","_isArrayIndex","n","_isOwnEnumerable","_safeEnumerables","floor","_keyToPairIn","_makeCriteria","sorters","map","_makeCriterion","_sorter","_makeReducer","step","accumulator","initialValue","nCalls","TypeError","_makeTypeErrorFor","desiredType","toLowerCase","_merge","getKeys","_partialWithIteratee","optionalArgument","f","binary","keys","_setIndex","updater","isUpdate","_setPathIn","v","setIn","reader","_toPathParts","path","separator","split","filter","adapter","allOf","predicates","anyOf","condition","trueFn","falseFn","applyArgsTo","applyArgs","is","isGT","isGTE","isLT","isLTE","not","add","min","max","divide","generate","limit","modulo","multiply","randomInt","random","range","remainder","subtract","isType","typeName","_objectProto","toString","call","replace","getAt","getIndex","getIn","getKey","getPath","getPathIn","pathInfo","setAt","enumerables","make","setKey","setPath","setPathIn","updateAt","updateIn","updateKey","updatePath","updatePathIn","contains","fromIndex","isIn","difference","rest","shallowFlatten","unary","isInRest","dropN","dropWhile","find","findIndex","flatten","insert","splice","insertAt","intersection","uniques","item","every","list","partition","el","pluck","_arrayProto","take","takeN","takeWhile","transpose","j","minLen","sort","data","sortedInsert","sortWith","aritize","collect","curry","curryable","curryableRight","curryRight","debounce","timespan","timeoutID","context","debounced","clearTimeout","setTimeout","flip","getArgAt","invoker","invokerOn","mapArgs","mapper","mapWith","tapArgs","tappers","tappersLen","throttle","lastCall","now","Date","checker","message","keyPaths","pathSeparator","getValues","fromPairs","pairsList","pair","has","hasKey","hasOwnKey","hasOwn","immutable","values","valuesLen","pick","whitelist","pickIf","rename","keysMap","oldKeys","prop","renameWith","skip","blacklist","validate","checkers","errors","padLeft","padRight","count","testWith","pattern","_reProto","test","lamb","create","_version","prototype","RegExp","generic","Function","propertyIsEnumerable","_pairsFrom","_safeKeys","_tearFrom","_unsafeKeyListFrom","_valuesFrom","filterWith","reduceRight","reduceRightWith","reduceWith","isNot","head","last","setIndex","updateIndex","drop","flatMap","flatMapWith","init","partitionWith","pluckKey","tail","union","zip","zipWithIndex","countBy","group","groupBy","indexBy","sorter","sorterDesc","pipe","wrap","hasKeyValue","hasOwnProperty","merge","mergeOwn","ownPairs","ownValues","pairs","pickKeys","renameKeys","skipIf","skipKeys","tear","tearOwn","validateWith","exports","module","define","amd"],"mappings":"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","file":"lamb.min.js","sourcesContent":["/**\n * @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming.\n * @author Andrea Scartabelli \n * @version 0.36.0-alpha.3\n * @module lamb\n * @license MIT\n * @preserve\n */\n!function (host) {\n \"use strict\";\n\n var lamb = Object.create(null);\n\n /**\n * The current module version.\n * @memberof module:lamb\n * @private\n * @category Core\n * @type String\n */\n lamb._version = \"0.36.0-alpha.3\";\n\n // alias used as a placeholder argument for partial application\n var _ = lamb;\n\n // some prototype shortcuts for internal use\n var _arrayProto = Array.prototype;\n var _objectProto = Object.prototype;\n var _reProto = RegExp.prototype;\n\n /**\n * Builds a function that returns a constant value.\n * It's actually the simplest form of the K combinator or Kestrel.\n * @example\n * var truth = _.always(true);\n *\n * truth() // => true\n * truth(false) // => true\n * truth(1, 2) // => true\n *\n * // the value being returned is actually the\n * // very same value passed to the function\n * var foo = {bar: \"baz\"};\n * var alwaysFoo = _.always(foo);\n *\n * alwaysFoo() === foo // => true\n *\n * @memberof module:lamb\n * @category Core\n * @see [SKI combinator calculus]{@link https://en.wikipedia.org/wiki/SKI_combinator_calculus}\n * @param {*} value\n * @returns {Function}\n */\n function always (value) {\n return function () {\n return value;\n };\n }\n\n /**\n * Returns a function that is the composition of the functions given as parameters.\n * Each function consumes the result of the function that follows.\n * @example\n * var sayHi = function (name) { return \"Hi, \" + name; };\n * var capitalize = function (s) {\n * return s[0].toUpperCase() + s.substr(1).toLowerCase();\n * };\n * var fixNameAndSayHi = _.compose(sayHi, capitalize);\n *\n * sayHi(\"bOb\") // => \"Hi, bOb\"\n * fixNameAndSayHi(\"bOb\") // \"Hi, Bob\"\n *\n * var getName = _.getKey(\"name\");\n * var users = [{name: \"fred\"}, {name: \"bOb\"}];\n * var sayHiToUser = _.compose(fixNameAndSayHi, getName);\n *\n * users.map(sayHiToUser) // [\"Hi, Fred\", \"Hi, Bob\"]\n *\n * @memberof module:lamb\n * @category Function\n * @param {...Function} fn\n * @returns {Function}\n */\n function compose () {\n var functions = arguments;\n\n return function () {\n var args = arguments;\n var len = functions.length;\n\n while (len--) {\n args = [functions[len].apply(this, args)];\n }\n\n return args[0];\n };\n }\n\n /**\n * Creates generic functions out of methods.\n * @memberof module:lamb\n * @category Core\n * @author A very little change on a great idea by [Irakli Gozalishvili]{@link https://github.com/Gozala/}. Thanks for this *beautiful* one-liner (never liked your \"unbind\" naming choice, though).\n * @function\n * @example\n * // Lamb's \"slice\" is actually implemented like this\n * var slice = _.generic(Array.prototype.slice);\n *\n * slice([\"foo\", \"bar\", \"baz\"], 0, -1) // => [\"foo\", \"bar\"]\n *\n * // the function will work with any array-like object\n * slice(\"fooBAR\", 0, 3) // => [\"f\", \"o\", \"o\"]\n *\n * @param {Function} method\n * @returns {Function}\n */\n var generic = Function.bind.bind(Function.call);\n\n /**\n * The I combinator. Any value passed to the function is simply returned as it is.\n * @example\n * var foo = {bar: \"baz\"};\n *\n * _.identity(foo) === foo // true\n *\n * @memberof module:lamb\n * @category Core\n * @see [SKI combinator calculus]{@link https://en.wikipedia.org/wiki/SKI_combinator_calculus}\n * @param {*} value\n * @returns {*} The value passed as parameter.\n */\n function identity (value) {\n return value;\n }\n\n /**\n * Builds a partially applied function. The lamb object itself can be used as a placeholder argument:\n * it's useful to alias it as _ or __.\n * @example\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n * var parseInt10 = _.partial(parseInt, _, 10);\n *\n * weights.map(parseInt10) // => [2, 10, 1, 7]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {...*} args\n * @returns {Function}\n */\n function partial (fn) {\n var args = slice(arguments, 1);\n\n return function () {\n var lastArgumentIdx = 0;\n var newArgs = [];\n var argsLen = args.length;\n\n for (var i = 0, boundArg; i < argsLen; i++) {\n boundArg = args[i];\n newArgs[i] = boundArg === _ ? arguments[lastArgumentIdx++] : boundArg;\n }\n\n for (var len = arguments.length; lastArgumentIdx < len; lastArgumentIdx++) {\n newArgs[i++] = arguments[lastArgumentIdx];\n }\n\n return fn.apply(this, newArgs);\n };\n }\n\n lamb.always = always;\n lamb.compose = compose;\n lamb.generic = generic;\n lamb.identity = identity;\n lamb.partial = partial;\n\n\n /**\n * The default comparer for sorting functions.
\n * If the given values are of different types they\n * will be both converted to strings.
\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\n function _comparer (a, b) {\n var result = 0;\n\n if (typeof a !== typeof b) {\n a = String(a);\n b = String(b);\n }\n\n if (!isSVZ(a, b)) {\n if (a > b || a !== a) {\n result = 1;\n } else if (a < b || b !== b) {\n result = -1;\n }\n }\n\n return result;\n }\n\n /**\n * Accepts a list of sorting criteria and builds a function that compares\n * two values with such criteria.\n * @private\n * @param {Sorter[]} criteria\n * @returns {Function}\n */\n function _compareWith (criteria) {\n var len = criteria.length;\n\n return function (a, b) {\n var result = 0;\n var isDescSort;\n var criterion;\n\n for (var i = 0; i < len; i++) {\n criterion = criteria[i];\n result = criterion.compare(a.value, b.value);\n\n if (result !== 0) {\n isDescSort = criteria[i].isDescending;\n break;\n }\n }\n\n if (result === 0) {\n isDescSort = criteria[len - 1].isDescending;\n result = a.index - b.index;\n }\n\n return isDescSort ? -result : result;\n };\n }\n\n /**\n * Used by curry functions to collect arguments until the arity is consumed,\n * then applies the original function.\n * @private\n * @param {Function} fn\n * @param {Number} arity\n * @param {Boolean} isRightCurry\n * @param {Function} slicer\n * @param {Array} argsHolder\n */\n function _currier (fn, arity, isRightCurry, slicer, argsHolder) {\n return function () {\n var args = argsHolder.concat(slicer(arguments));\n\n if (args.length >= arity) {\n return fn.apply(this, isRightCurry ? args.reverse() : args);\n } else {\n return _currier(fn, arity, isRightCurry, slicer, args);\n }\n };\n }\n\n /**\n * Prepares a function for currying by setting the proper parameters for\n * the _currier function.\n * If the desumed arity isn't greater than one, it will return the received\n * function itself, instead.\n * @private\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @param {Boolean} isRightCurry\n * @param {Boolean} isAutoCurry\n */\n function _curry (fn, arity, isRightCurry, isAutoCurry) {\n var slicer = isAutoCurry ? function (argsObj) {\n var len = argsObj.length;\n\n if (len) {\n for (var i = 0, args = []; i < len; i++) {\n args[i] = argsObj[i];\n }\n\n return args;\n } else {\n return [void 0];\n }\n } : function (argsObj) {\n return argsObj.length ? [argsObj[0]] : [void 0];\n };\n\n if ((arity >>> 0) !== arity) {\n arity = fn.length;\n }\n\n return arity > 1 ? _currier(fn, arity, isRightCurry, slicer, []) : fn;\n }\n\n /**\n * Flattens an array.\n * @private\n * @param {Array} array\n * @param {Array} output The empty array to collect the result\n * @returns {Array} The output array filled with the results\n */\n function _flatten (array, output) {\n forEach(array, function (value) {\n if (Array.isArray(value)) {\n _flatten(value, output);\n } else {\n output.push(value);\n }\n });\n\n return output;\n }\n\n /**\n * Establishes at which index an element should be inserted in a sorted array to respect\n * the array order. Needs the comparer used to sort the array.\n * @param {Array} array\n * @param {*} element\n * @param {Function} comparer\n * @param {Number} start\n * @param {Number} end\n * @private\n */\n function _getInsertionIndex (array, element, comparer, start, end) {\n if (array.length === 0) {\n return 0;\n }\n\n var pivot = (start + end) >> 1;\n var result = comparer({\n value: element,\n index: pivot\n }, {\n value: array[pivot],\n index: pivot\n });\n\n if (end - start <= 1) {\n return result < 0 ? pivot : pivot + 1;\n } else if (result < 0) {\n return _getInsertionIndex(array, element, comparer, start, pivot);\n } else if (result === 0) {\n return pivot + 1;\n } else {\n return _getInsertionIndex(array, element, comparer, pivot, end);\n }\n }\n\n /**\n * Checks if the given index, even negative, exists in the target object, if\n * it's an array-like, and transforms it to a natural number.\n * Returns undefined otherwise.\n * @private\n * @param {ArrayLike} target\n * @param {Number} index\n * @returns {Number|undefined}\n */\n function _getNaturalIndex (target, index) {\n var len = target.length;\n\n if (_isInteger(index) && _isInteger(len)) {\n return clamp(index, -len, len - 1) === index ? index < 0 ? index + len : index : void 0;\n }\n }\n\n /**\n * Gets the number of consecutive elements satisfying a predicate in an array-like object.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {Function} predicate\n * @param {Object} predicateContext\n */\n function _getNumConsecutiveHits (arrayLike, predicate, predicateContext) {\n var idx = -1;\n var len = arrayLike.length;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n while (++idx < len && predicate(arrayLike[idx], idx, arrayLike));\n\n return idx;\n }\n\n /**\n * Builds the prefix or suffix to be used when padding a string.\n * @private\n * @param {String} source\n * @param {String} char\n * @param {Number} len\n * @returns {String}\n */\n function _getPadding (source, char, len) {\n if (!isNil(source) && type(source) !== \"String\") {\n source = String(source);\n }\n\n return repeat(Object(char)[0] || \" \", Math.ceil(len - source.length));\n }\n\n /**\n * Checks if a path is valid in the given object and retrieves the path target.\n * @private\n * @param {Object} obj\n * @param {String[]} parts\n * @param {Boolean} walkNonEnumerables\n * @returns {Object}\n */\n function _getPathInfo (obj, parts, walkNonEnumerables) {\n var target = obj;\n var i = -1;\n var len = parts.length;\n var key;\n var keyAsNumber;\n\n while (++i < len) {\n key = parts[i];\n\n if (!(_isEnumerable(target, key) || key in Object(target) && walkNonEnumerables)) {\n keyAsNumber = Number(key);\n key = keyAsNumber < 0 ? _getNaturalIndex(target, keyAsNumber) : void 0;\n }\n\n if (isUndefined(key)) {\n break;\n }\n\n target = target[key];\n }\n\n return i === len ? {isValid: true, target: target} : {isValid: false, target: void 0};\n }\n\n /**\n * Builds a \"grouping function\" for an array-like object.\n * @private\n * @param {Function} makeValue\n * @param {*} startValue\n * @returns {Function}\n */\n function _groupWith (makeValue, startValue) {\n return function (arrayLike, iteratee, iterateeContext) {\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n return reduce(arrayLike, function (result, element, idx) {\n var key = iteratee(element, idx, arrayLike);\n var value = makeValue(key in result ? result[key] : startValue , element);\n\n result[key] = value;\n\n return result;\n }, {});\n };\n }\n\n /**\n * Makes an object immutable by recursively calling Object.freeze\n * on its members.\n * @private\n * @param {Object} obj\n * @param {Array} seen\n * @returns {Object} The obj parameter itself, not a copy.\n */\n function _immutable (obj, seen) {\n if (seen.indexOf(obj) === -1) {\n seen.push(Object.freeze(obj));\n\n forEach(Object.getOwnPropertyNames(obj), function (key) {\n var value = obj[key];\n\n if (typeof value === \"object\" && !isNull(value)) {\n _immutable(value, seen);\n }\n });\n }\n\n return obj;\n }\n\n /**\n * If a method with the given name exists on the target, applies it with the provided\n * arguments and returns the result. Returns undefined otherwise.
\n * The arguments for the method are built by concatenating the array of bound arguments,\n * optionally received by {@link module:lamb.invoker|invoker}, with the final set of, also\n * optional, args.\n * @private\n * @param {Array} boundArgs\n * @param {String} methodName\n * @param {Object} target\n * @param {...*} [args]\n * @returns {*}\n */\n function _invoker (boundArgs, methodName, target) {\n var args = boundArgs.concat(slice(arguments, 3));\n var method = target[methodName];\n return type(method) === \"Function\" ? method.apply(target, args) : void 0;\n }\n\n /**\n * Accepts a target object and a key name and verifies that the target is an array and that\n * the key is an existing index.\n * @private\n * @param {Object} target\n * @param {String|Number} key\n * @returns {Boolean}\n */\n function _isArrayIndex (target, key) {\n var n = Number(key);\n return Array.isArray(target) && _isInteger(n) && !(n < 0 && _isEnumerable(target, key));\n }\n\n /**\n * Checks whether the specified key is an enumerable property of the given object or not.\n * @private\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n function _isEnumerable (obj, key) {\n return key in Object(obj) && (_isOwnEnumerable(obj, key) || ~_safeEnumerables(obj).indexOf(key));\n }\n\n /**\n * Checks if the given value is an integer.\n * @private\n * @param {*} n\n * @returns {Boolean}\n */\n function _isInteger (n) {\n return Math.floor(n) === n;\n }\n\n /**\n * Checks whether the specified key is a own enumerable property of the given object or not.\n * @private\n * @function\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n var _isOwnEnumerable = generic(_objectProto.propertyIsEnumerable);\n\n /**\n * Accepts an object and build a function expecting a key to create a \"pair\" with the key\n * and its value.\n * @private\n * @param {Object} obj\n * @returns {Function}\n */\n function _keyToPairIn (obj) {\n return function (key) {\n return [key, obj[key]];\n };\n }\n\n /**\n * Builds a list of sorting criteria from a list of sorter functions. Returns a list containing\n * a single default sorting criterion if the sorter list is empty.\n * @private\n * @param {Function[]} sorters\n * @returns {Sorter[]}\n */\n function _makeCriteria (sorters) {\n return sorters.length ? map(sorters, _makeCriterion) : [_sorter()];\n }\n\n /**\n * Converts a sorting function to a sorting criterion if necessary.\n * @private\n * @param {Function} criterion\n * @returns {Sorter}\n */\n function _makeCriterion (criterion) {\n return typeof Object(criterion).compare === \"function\" ? criterion : _sorter(criterion);\n }\n\n /**\n * Builds a reduce function. The step parameter must be 1\n * to build {@link module:lamb.reduce|reduce} and -1 to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\n function _makeReducer (step) {\n return function (arrayLike, accumulator, initialValue) {\n var len = arrayLike.length >>> 0;\n var idx = step === 1 ? 0 : len - 1;\n var nCalls;\n var result;\n\n if (arguments.length === 3) {\n nCalls = len;\n result = initialValue;\n } else {\n if (len === 0) {\n throw new TypeError(\"Reduce of empty array-like with no initial value\");\n }\n\n result = arrayLike[idx];\n idx += step;\n nCalls = len - 1;\n }\n\n for (; nCalls--; idx += step) {\n result = accumulator(result, arrayLike[idx], idx, arrayLike);\n }\n\n return result;\n };\n }\n\n /**\n * Builds a TypeError stating that it's not possible to convert the given value to the\n * desired type.\n * @private\n * @param {*} value\n * @param {String} desiredType\n * @returns {TypeError}\n */\n function _makeTypeErrorFor(value, desiredType) {\n return new TypeError(\"Cannot convert \" + type(value).toLowerCase() + \" to \" + desiredType);\n }\n\n /**\n * Merges the received objects using the provided functions to retrieve their keys.\n * @private\n * @param {Function} getKeys\n * @param {...Object} source\n * @returns {Object}\n */\n function _merge (getKeys) {\n return reduce(slice(arguments, 1), function (result, source) {\n forEach(getKeys(source), function (key) {\n result[key] = source[key];\n });\n\n return result;\n }, {});\n }\n\n /**\n * Using the provided function to retrieve the keys of an object, builds\n * a function expecting an object to create a list of key / value pairs.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _pairsFrom = _curry(function (getKeys, obj) {\n return map(getKeys(obj), _keyToPairIn(obj));\n });\n\n /**\n * Builds a partial application of a function expecting an iteratee and an\n * optional argument other than its main data parameter.
\n * The optional argument is passed to the function only when is explicitly given\n * a value.
\n * The optional argument is usually the iteratee context, but reduce functions\n * pass their initial value instead.\n * @private\n * @param {Function} fn\n * @returns {Function}\n */\n function _partialWithIteratee (fn) {\n return function (iteratee, optionalArgument) {\n var f = arguments.length === 2 ? fn : binary(fn);\n return partial(f, _, iteratee, optionalArgument);\n };\n }\n\n /**\n * Builds a list of the enumerable properties of an object.\n * The function is null-safe, unlike the public one.\n * @private\n * @param {Object} obj\n * @returns {String[]}\n */\n function _safeEnumerables (obj) {\n var keys = [];\n\n for (var key in obj) {\n keys.push(key);\n }\n\n return keys;\n }\n\n /**\n * A null-safe version of Object.keys.\n * @private\n * @param {Object} obj\n * @returns {String[]}\n */\n var _safeKeys = compose(Object.keys, Object);\n\n /**\n * Sets an index in an array-like object.
\n * If provided with an updater function it will use it to update the current value,\n * otherwise sets the index to the specified value.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} [value]\n * @param {Function} [updater]\n */\n function _setIndex (arrayLike, index, value, updater) {\n var result = slice(arrayLike);\n var idx = _getNaturalIndex(result, index);\n var isUpdate = arguments.length === 4;\n\n if (!isUndefined(idx)) {\n result[idx] = isUpdate ? updater(arrayLike[idx]) : value;\n }\n\n return result;\n }\n\n /**\n * Sets the object's property targeted by the given path to the desired value.
\n * Works with arrays and is able to set their indexes, even negative ones.\n * @private\n * @param {Object|Array} obj\n * @param {String[]} parts\n * @param {*} value\n * @returns {Object|Array}\n */\n function _setPathIn (obj, parts, value) {\n var key = parts[0];\n var v = parts.length === 1 ? value : _setPathIn(\n _getPathInfo(obj, [key], false).target,\n slice(parts, 1),\n value\n );\n\n return _isArrayIndex(obj, key) ? _setIndex(obj, +key, v) : setIn(Object(obj), key, v);\n }\n\n /**\n * Builds a sorting criterion. If the comparer function is missing, the default\n * comparer will be used instead.\n * @param {Function} reader\n * @param {Boolean} isDescending\n * @param {Function} [comparer]\n * @private\n */\n function _sorter (reader, isDescending, comparer) {\n return {\n isDescending: isDescending === true,\n compare: function (a, b) {\n if (typeof reader === \"function\" && reader !== identity) {\n a = reader(a);\n b = reader(b);\n }\n\n return (typeof comparer === \"function\" ? comparer : _comparer)(a, b);\n }\n };\n }\n\n /**\n * Using the provided function to retrieve the keys of an object, builds\n * a function expecting an object to create an array containing a list\n * of the keys in its first index and the corresponding list of values\n * in the second one.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _tearFrom = _curry(function (getKeys, obj) {\n return reduce(getKeys(obj), function (result, key) {\n result[0].push(key);\n result[1].push(obj[key]);\n return result;\n }, [[], []]);\n });\n\n /**\n * Splits a sting path using the provided separator and returns an array\n * of path parts.\n * @private\n * @param {String} path\n * @param {String} separator\n * @returns {String[]}\n */\n function _toPathParts (path, separator) {\n return String(path).split(separator || \".\");\n }\n\n /**\n * Creates a non-null-safe version of the provided \"getKeys\" function.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _unsafeKeyListFrom = _curry(function (getKeys, obj) {\n return (isNil(obj) ? Object.keys : getKeys)(obj);\n });\n\n /**\n * Using the provided function to retrieve the keys of an object, builds\n * a function expecting an object to create the list of values for such keys.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\n var _valuesFrom = _curry(function (getKeys, obj) {\n return map(getKeys(obj), partial(getIn, obj));\n });\n\n\n /**\n * Builds an array comprised of all values of the array-like object passing the predicate test.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.filter]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * var isLowerCase = function (s) { return s.toLowerCase() === s; };\n *\n * _.filter([\"Foo\", \"bar\", \"baZ\"], isLowerCase) // => [\"bar\"]\n *\n * // the function will work with any array-like object\n * _.filter(\"fooBAR\", isLowerCase) // => [\"f\", \"o\", \"o\"]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.filterWith|filterWith}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Array}\n */\n function filter (arrayLike, predicate, predicateContext) {\n var len = arrayLike.length;\n var result = [];\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0; i < len; i++) {\n predicate(arrayLike[i], i, arrayLike) && result.push(arrayLike[i]);\n }\n\n return result;\n }\n\n /**\n * Returns a partial application of {@link module:lamb.filter|filter} that uses the given predicate and\n * the optional context to build a function expecting the array-like object to act upon.\n * @example\n * var isLowerCase = function (s) { return s.toLowerCase() === s; };\n * var getLowerCaseEntries = _.filterWith(isLowerCase);\n *\n * getLowerCaseEntries([\"Foo\", \"bar\", \"baZ\"]) // => [\"bar\"]\n *\n * // array-like objects can be used as well\n * getLowerCaseEntries(\"fooBAR\") // => [\"f\", \"o\", \"o\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.filter|filter}\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n var filterWith = _partialWithIteratee(filter);\n\n /**\n * Executes the provided iteratee for each element of the given array-like object.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.forEach]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example Adding a CSS class to all elements of a NodeList in a browser environment\n * var addClass = _.curry(function (className, element) {\n * element.classList.add(className);\n * });\n * var paragraphs = document.querySelectorAll(\"#some-container p\");\n *\n * _.forEach(paragraphs, addClass(\"main\"));\n * // each \"p\" element in the container will have the \"main\" class now\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n */\n function forEach (arrayLike, iteratee, iterateeContext) {\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n for (var i = 0, len = arrayLike.length >>> 0; i < len; i++) {\n iteratee(arrayLike[i], i, arrayLike);\n }\n }\n\n /**\n * Builds a new array by applying the iteratee function to each element of the\n * received array-like object.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.map]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * _.map([\"Joe\", \"Mario\", \"Jane\"], _.invoker(\"toUpperCase\")) // => [\"JOE\", \"MARIO\", \"JANE\"]\n *\n * _.map([4, 9, 16], Math.sqrt); // => [2, 3, 4]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.mapWith|mapWith}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n function map (arrayLike, iteratee, iterateeContext) {\n var len = arrayLike.length >>> 0;\n var result = Array(len);\n\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n for (var i = 0; i < len; i++) {\n result[i] = iteratee(arrayLike[i], i, arrayLike);\n }\n\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.map|map} using the given iteratee and the optional context.\n * The resulting function expects the array-like object to act upon.\n * @example\n * var square = function (n) { return n * n; };\n * var getSquares = _.mapWith(square);\n *\n * getSquares([1, 2, 3, 4, 5]) // => [1, 4, 9, 16, 25]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.map|map}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {function}\n */\n var mapWith = _partialWithIteratee(map);\n\n /**\n * Reduces (or folds) the values of an array-like object, starting from the first, to a new\n * value using the provided accumulator function.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.reduce]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * _.reduce([1, 2, 3, 4], _.add) // => 10\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduceRight|reduceRight}\n * @see {@link module:lamb.reduceWith|reduceWith}, {@link module:lamb.reduceRightWith|reduceRightWith}\n * @param {ArrayLike} arrayLike\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {*}\n */\n var reduce = _makeReducer(1);\n\n /**\n * Same as {@link module:lamb.reduce|reduce}, but starts the fold operation from the last element instead.
\n * Since version 0.34.0 this function is no longer a generic version of\n * [Array.prototype.reduceRight]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight}\n * for performance reasons.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduce|reduce}\n * @see {@link module:lamb.reduceWith|reduceWith}, {@link module:lamb.reduceRightWith|reduceRightWith}\n * @param {ArrayLike} arrayLike\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {*}\n */\n var reduceRight = _makeReducer(-1);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduceRight} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.reduceRightWith(_.add)(arr) // => 15\n * _.reduceRightWith(_.subtract)(arr) // => -5\n * _.reduceRightWith(_.subtract, 0)(arr) // => -15\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduceWith|reduceWith}\n * @see {@link module:lamb.reduce|reduce}, {@link module:lamb.reduce|reduceRight}\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {Function}\n */\n var reduceRightWith = _partialWithIteratee(reduceRight);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduce} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.reduceWith(_.add)(arr) // => 15\n * _.reduceWith(_.subtract)(arr) // => -13\n * _.reduceWith(_.subtract, 0)(arr) // => -15\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.reduceRightWith|reduceRightWith}\n * @see {@link module:lamb.reduce|reduce}, {@link module:lamb.reduce|reduceRight}\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {Function}\n */\n var reduceWith = _partialWithIteratee(reduce);\n\n /**\n * Builds an array by extracting a portion of an array-like object.
\n * It's a generic version of [Array.prototype.slice]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice}.\n * @example\n * _.slice([\"foo\", \"bar\", \"baz\"], 0, 2) // => [\"foo\", \"bar\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {ArrayLike} arrayLike - Any array like object.\n * @param {Number} [start=0] - Zero-based index at which to begin extraction.\n * @param {Number} [end=arrayLike.length] - Zero-based index at which to end extraction. Extracts up to but not including end.\n * @returns {Array}\n */\n var slice = generic(_arrayProto.slice);\n\n lamb.filter = filter;\n lamb.filterWith = filterWith;\n lamb.forEach = forEach;\n lamb.map = map;\n lamb.mapWith = mapWith;\n lamb.reduce = reduce;\n lamb.reduceRight = reduceRight;\n lamb.reduceRightWith = reduceRightWith;\n lamb.reduceWith = reduceWith;\n lamb.slice = slice;\n\n\n /**\n * Accepts a series of functions and builds a function that applies the received arguments to each one and\n * returns the first non-undefined value.
\n * Meant to work in sinergy with {@link module:lamb.condition|condition} and {@link module:lamb.invoker|invoker},\n * can be useful as a strategy pattern for functions, to mimic conditional logic and also to build polymorphic functions.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var filterString = _.compose(_.invoker(\"join\", \"\"), _.filter);\n * var filterAdapter = _.adapter(\n * _.invoker(\"filter\"),\n * _.condition(_.isType(\"String\"), filterString)\n * );\n *\n * filterAdapter([1, 2, 3, 4, 5, 6], isEven) // => [2, 4, 6]\n * filterAdapter(\"123456\", isEven) // => \"246\"\n * filterAdapter({}, isEven) // => undefined\n *\n * // obviously it's composable\n * var filterWithDefault = _.adapter(filterAdapter, _.always(\"Not implemented\"));\n *\n * filterWithDefault([1, 2, 3, 4, 5, 6], isEven) // => [2, 4, 6]\n * filterWithDefault(\"123456\", isEven) // => \"246\"\n * filterWithDefault({}, isEven) // => \"Not implemented\"\n *\n * @memberof module:lamb\n * @category Logic\n * @param {...Function} fn\n * @returns {Function}\n */\n function adapter () {\n var functions = slice(arguments);\n\n return function () {\n var len = functions.length;\n var result;\n\n for (var i = 0; i < len; i++) {\n result = functions[i].apply(this, arguments);\n\n if (!isUndefined(result)) {\n break;\n }\n }\n\n return result;\n };\n }\n\n /**\n * Builds a predicate that returns true if all the given predicates are satisfied.\n * The arguments passed to the resulting function are applied to every predicate unless one of them returns false.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var isPositive = function (n) { return n > 0; };\n * var isPositiveEven = _.allOf(isEven, isPositive);\n *\n * isPositiveEven(-2) // => false\n * isPositiveEven(11) // => false\n * isPositiveEven(6) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.anyOf|anyOf}\n * @param {...Function} predicate\n * @returns {Function}\n */\n function allOf () {\n var predicates = slice(arguments);\n\n return function () {\n for (var i = 0, len = predicates.length; i < len; i++) {\n if(!predicates[i].apply(this, arguments)) {\n return false;\n }\n }\n\n return true;\n };\n }\n\n /**\n * Builds a predicate that returns true if at least one of the given predicates is satisfied.\n * The arguments passed to the resulting function are applied to every predicate until one of them returns true.\n * @example\n * var users = [\n * {id: 1, name: \"John\", group: \"guest\"},\n * {id: 2, name: \"Jane\", group: \"root\"},\n * {id: 3, name: \"Mario\", group: \"admin\"}\n * ];\n * var isInGroup = _.partial(_.hasKeyValue, \"group\");\n * var isSuperUser = _.anyOf(isInGroup(\"admin\"), isInGroup(\"root\"));\n *\n * isSuperUser(users[0]) // => false\n * isSuperUser(users[1]) // => true\n * isSuperUser(users[2]) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.allOf|allOf}\n * @param {...Function} predicate\n * @returns {Function}\n */\n function anyOf () {\n var predicates = slice(arguments);\n\n return function () {\n for (var i = 0, len = predicates.length; i < len; i++) {\n if (predicates[i].apply(this, arguments)) {\n return true;\n }\n }\n\n return false;\n };\n }\n\n /**\n * Builds a function that will apply the received arguments to trueFn, if the predicate is satisfied with\n * the same arguments, or to falseFn otherwise.
\n * If falseFn isn't provided and the predicate isn't satisfied the function will return undefined.
\n * Although you can use other conditions as trueFn or falseFn, it's probably better to\n * use {@link module:lamb.adapter|adapter} to build more complex behaviours.\n * @example\n * var isEven = function (n) { return n % 2 === 0};\n * var halve = function (n) { return n / 2; };\n * var halveIfEven = _.condition(isEven, halve, _.identity);\n *\n * halveIfEven(5) // => 5\n * halveIfEven(6) // => 3\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.invoker|invoker}\n * @param {Function} predicate\n * @param {Function} trueFn\n * @param {Function} [falseFn]\n * @returns {Function}\n */\n function condition (predicate, trueFn, falseFn) {\n return function () {\n var applyArgsTo = applyArgs(arguments);\n return applyArgsTo(predicate) ? applyArgsTo(trueFn) : falseFn ? applyArgsTo(falseFn) : void 0;\n };\n }\n\n /**\n * Verifies that the two supplied values are the same value using the \"SameValue\" comparison.
\n * Note that this doesn't behave as the strict equality operator, but rather as a shim of ES6's\n * [Object.is]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is}.\n * Differences are that 0 and -0 aren't the same value and, finally, NaN is equal to itself.
\n * See also {@link module:lamb.isSVZ|isSVZ} which performs the check using the \"SameValueZero\" comparison.\n * @example\n * var testObject = {};\n *\n * _.is({}, testObject) // => false\n * _.is(testObject, testObject) // => true\n * _.is(\"foo\", \"foo\") // => true\n * _.is(0, -0) // => false\n * _.is(0 / 0, NaN) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see [SameValue comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero}\n * @param {*} a\n * @param {*} b\n * @returns {Boolean}\n */\n function is (a, b) {\n return a === 0 && b === 0 ? 1 / a === 1 / b : isSVZ(a, b);\n }\n\n /**\n * Verifies that the first given value is greater than the second.\n * @example\n * var pastDate = new Date(2010, 2, 12);\n * var today = new Date();\n *\n * _.isGT(today, pastDate) // true\n * _.isGT(pastDate, today) // false\n * _.isGT(3, 4) // false\n * _.isGT(3, 3) // false\n * _.isGT(3, 2) // true\n * _.isGT(0, -0) // false\n * _.isGT(-0, 0) // false\n * _.isGT(\"a\", \"A\") // true\n * _.isGT(\"b\", \"a\") // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isGT (a, b) {\n return a > b;\n }\n\n /**\n * Verifies that the first given value is greater than or equal to the second.\n * Regarding equality, beware that this is simply a wrapper for the native operator, so -0 === 0.\n * @example\n * _.isGTE(3, 4) // false\n * _.isGTE(3, 3) // true\n * _.isGTE(3, 2) // true\n * _.isGTE(0, -0) // true\n * _.isGTE(-0, 0) // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isGTE (a, b) {\n return a >= b;\n }\n\n /**\n * Verifies that the first given value is less than the second.\n * @example\n * var pastDate = new Date(2010, 2, 12);\n * var today = new Date();\n *\n * _.isLT(today, pastDate) // false\n * _.isLT(pastDate, today) // true\n * _.isLT(3, 4) // true\n * _.isLT(3, 3) // false\n * _.isLT(3, 2) // false\n * _.isLT(0, -0) // false\n * _.isLT(-0, 0) // false\n * _.isLT(\"a\", \"A\") // false\n * _.isLT(\"a\", \"b\") // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isLT (a, b) {\n return a < b;\n }\n\n /**\n * Verifies that the first given value is less than or equal to the second.\n * Regarding equality, beware that this is simply a wrapper for the native operator, so -0 === 0.\n * @example\n * _.isLTE(3, 4) // true\n * _.isLTE(3, 3) // true\n * _.isLTE(3, 2) // false\n * _.isLTE(0, -0) // true\n * _.isLTE(-0, 0) // true\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\n function isLTE (a, b) {\n return a <= b;\n }\n\n /**\n * A simple negation of {@link module:lamb.is|is}, exposed for convenience.\n * @example\n * _.isNot(\"foo\", \"foo\") // => false\n * _.isNot(0, -0) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @param {*} valueA\n * @param {*} valueB\n * @returns {Boolean}\n */\n var isNot = not(is);\n\n /**\n * Verifies that the two supplied values are the same value using the \"SameValueZero\" comparison.
\n * With this comparison NaN is equal to itself, but 0 and -0 are\n * considered the same value too.
\n * See also {@link module:lamb.is|is} to perform a \"SameValue\" comparison.\n * @example\n * var testObject = {};\n *\n * _.isSVZ({}, testObject) // => false\n * _.isSVZ(testObject, testObject) // => true\n * _.isSVZ(\"foo\", \"foo\") // => true\n * _.isSVZ(0, -0) // => true\n * _.isSVZ(0 / 0, NaN) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see [SameValue comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero}\n * @param {*} a\n * @param {*} b\n * @returns {Boolean}\n */\n function isSVZ (a, b) {\n return a !== a ? b !== b : a === b;\n }\n\n /**\n * Returns a predicate that negates the given one.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var isOdd = _.not(isEven);\n *\n * isOdd(5) // => true\n * isOdd(4) // => false\n *\n * @memberof module:lamb\n * @category Logic\n * @param {Function} predicate\n * @returns {Function}\n */\n function not (predicate) {\n return function () {\n return !predicate.apply(this, arguments);\n };\n }\n\n lamb.adapter = adapter;\n lamb.allOf = allOf;\n lamb.anyOf = anyOf;\n lamb.condition = condition;\n lamb.is = is;\n lamb.isGT = isGT;\n lamb.isGTE = isGTE;\n lamb.isLT = isLT;\n lamb.isLTE = isLTE;\n lamb.isNot = isNot;\n lamb.isSVZ = isSVZ;\n lamb.not = not;\n\n\n /**\n * Adds two numbers.\n * @example\n * _.add(4, 5) // => 9\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function add (a, b) {\n return a + b;\n }\n\n /**\n * \"Clamps\" a number within the given limits.\n * @example\n * _.clamp(-5, 0, 10) // => 0\n * _.clamp(5, 0, 10) // => 5\n * _.clamp(15, 0, 10) // => 10\n * _.clamp(0, 0, 10) // => 0\n * _.clamp(10, 0, 10) // => 10\n * _.is(_.clamp(-0, 0, 10), -0) // => true\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} n\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n function clamp (n, min, max) {\n return n < min ? min : n > max ? max : n;\n }\n\n /**\n * Divides two numbers.\n * @example\n * _.divide(5, 2) // => 2.5\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function divide (a, b) {\n return a / b;\n }\n\n /**\n * Generates a sequence of values of the desired length with the provided iteratee.\n * The values being iterated, and received by the iteratee, are the results generated so far.\n * @example\n * var fibonacci = function (n, idx, results) {\n * return n + (results[idx - 1] || 0);\n * };\n *\n * _.generate(1, 10, fibonacci) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n *\n * @memberof module:lamb\n * @category Math\n * @param {*} start - The starting value\n * @param {Number} len - The desired length for the sequence\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n function generate (start, len, iteratee, iterateeContext) {\n var result = [start];\n\n if (arguments.length === 4) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n for (var i = 0, limit = len - 1; i < limit; i++) {\n result.push(iteratee(result[i], i, result));\n }\n\n return result;\n }\n\n /**\n * Performs the modulo operation and should not be confused with the {@link module:lamb.remainder|remainder}.\n * The function performs a floored division to calculate the result and not a truncated one, hence the sign of\n * the dividend is not kept, unlike the {@link module:lamb.remainder|remainder}.\n * @example\n * _.modulo(5, 3) // => 2\n * _.remainder(5, 3) // => 2\n *\n * _.modulo(-5, 3) // => 1\n * _.remainder(-5, 3) // => -2\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link http://en.wikipedia.org/wiki/Modulo_operation}\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function modulo (a, b) {\n return a - (b * Math.floor(a / b));\n }\n\n /**\n * Multiplies two numbers.\n * @example\n * _.multiply(5, 3) // => 15\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function multiply (a, b) {\n return a * b;\n }\n\n /**\n * Generates a random integer between two given integers, both included.\n * Note that no safety measure is taken if the provided arguments aren't integers, so\n * you may end up with unexpected (not really) results.\n * For example randomInt(0.1, 1.2) could be 2.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n function randomInt (min, max) {\n return Math.floor(Math.random() * (max - min + 1) + min);\n }\n\n /**\n * Generates an arithmetic progression of numbers starting from start up to,\n * but not including, limit, using the given step.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(2, 10, 0) // => [2]\n * _.range(1, -10, -2) // => [1, -1, -3, -5, -7, -9]\n * _.range(1, -10, 2) // => [1]\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} start\n * @param {Number} limit\n * @param {Number} [step=1]\n * @returns {Number[]}\n */\n function range (start, limit, step) {\n if (step === 0 || arguments.length < 2) {\n return [start];\n }\n\n if (!step) {\n step = 1;\n }\n\n var len = Math.max(Math.ceil((limit - start) / step), 0);\n return generate(start, len, partial(add, step));\n }\n\n /**\n * Gets the remainder of the division of two numbers.\n * Not to be confused with the {@link module:lamb.modulo|modulo} as the remainder\n * keeps the sign of the dividend and may lead to some unexpected results.\n * @example\n * // example of wrong usage of the remainder\n * // (in this case the modulo operation should be used)\n * var isOdd = function (n) { return _.remainder(n, 2) === 1; };\n * isOdd(-3) // => false as -3 % 2 === -1\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link http://en.wikipedia.org/wiki/Modulo_operation}\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function remainder (a, b) {\n return a % b;\n }\n\n /**\n * Subtracts two numbers.\n * @example\n * _.subtract(5, 3) // => 2\n *\n * @memberof module:lamb\n * @category Math\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function subtract (a, b) {\n return a - b;\n }\n\n lamb.add = add;\n lamb.clamp = clamp;\n lamb.divide = divide;\n lamb.generate = generate;\n lamb.modulo = modulo;\n lamb.multiply = multiply;\n lamb.randomInt = randomInt;\n lamb.range = range;\n lamb.remainder = remainder;\n lamb.subtract = subtract;\n\n\n /**\n * Verifies if a value is null or undefined.\n * @example\n * _.isNil(NaN) // => false\n * _.isNil({}) // => false\n * _.isNil(null) // => true\n * _.isNil(void 0) // => true\n * _.isNil() // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNull|isNull} and {@link module:lamb.isNull|isUndefined} for individual checks.\n * @param {*} value\n * @returns {Boolean}\n */\n function isNil (value) {\n return isNull(value) || isUndefined(value);\n }\n\n /**\n * Verifies if a value is null.\n * @example\n * _.isNull(null) // => true\n * _.isNull(void 0) // => false\n * _.isNull(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for undefined too.\n * @param {*} value\n * @returns {Boolean}\n */\n function isNull (value) {\n return value === null;\n }\n\n /**\n * Builds a predicate that expects a value to check against the specified type.\n * @example\n * var isString = _.isType(\"String\");\n *\n * isString(\"Hello\") // => true\n * isString(new String(\"Hi\")) // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.type|type}\n * @param {String} typeTag\n * @returns {Function}\n */\n function isType (typeName) {\n return function (value) {\n return type(value) === typeName;\n };\n }\n\n /**\n * Verifies if a value is undefined.\n * @example\n * _.isUndefined(null) // => false\n * _.isUndefined(void 0) // => true\n * _.isUndefined(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for null too.\n * @param {*} value\n * @returns {Boolean}\n */\n function isUndefined (value) {\n // using void because undefined could be theoretically shadowed\n return value === void 0;\n }\n\n /**\n * Retrieves the \"type tag\" from the given value.\n * @example\n * var x = 5;\n * var y = new Number(5);\n *\n * typeof x // => \"number\"\n * typeof y // => \"object\"\n * _.type(x) // => \"Number\"\n * _.type(y) // => \"Number\"\n *\n * _.type(Object.prototype.toString) // => \"Function\"\n * _.type(/a/) // => \"RegExp\"\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isType|isType}\n * @param {*} value\n * @returns {String}\n */\n function type (value) {\n return _objectProto.toString.call(value).replace(/^\\[\\w+\\s+|\\]$/g, \"\");\n }\n\n lamb.isNil = isNil;\n lamb.isNull = isNull;\n lamb.isType = isType;\n lamb.isUndefined = isUndefined;\n lamb.type = type;\n\n\n /**\n * A curried version of {@link module:lamb.getIndex|getIndex} that uses the provided index\n * to build a function expecting the array-like object holding the element we want to retrieve.\n * @example\n * var getFifthElement = _.getAt(4);\n *\n * getFifthElement([1, 2, 3, 4, 5]) // => 5\n * getFifthElement(\"foo bar\") // => \"b\"\n * getFifthElement([]) // => undefined\n * getFifthElement(\"foo\") // => undefined\n *\n * @example Using negative indexes\n * _.getAt(-2)([1, 2, 3]) // => 2\n * _.getAt(-3)(\"foo\") // => \"f\"\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.getIndex|getIndex}\n * @see {@link module:lamb.head|head} and {@link module:lamb.last|last} for common use cases shortcuts.\n * @param {Number} index\n * @returns {Function}\n */\n function getAt (index) {\n return function (arrayLike) {\n return getIndex(arrayLike, index);\n };\n }\n\n /**\n * Returns the value of the object property with the given key.\n * @example\n * var user = {name: \"John\"};\n *\n * _.getIn(user, \"name\") // => \"John\";\n * _.getIn(user, \"surname\") // => undefined\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getKey|getKey}\n * @see {@link module:lamb.getPath|getPath}, {@link module:lamb.getPathIn|getPathIn}\n * @param {Object} obj\n * @param {String} key\n * @returns {*}\n */\n function getIn (obj, key) {\n return obj[key];\n }\n\n /**\n * Retrieves the element at the given index in an array-like object.
\n * Like {@link module:lamb.slice|slice} the index can be negative.
\n * If the index isn't supplied, or if its value isn't an integer within the array-like bounds,\n * the function will return undefined.
\n * getIndex will throw an exception when receives null or\n * undefined in place of an array-like object, but returns undefined\n * for any other value.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.getIndex(arr, 1) // => 2\n * _.getIndex(arr, -1) // => 5\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.getAt|getAt}\n * @see {@link module:lamb.head|head} and {@link module:lamb.last|last} for common use cases shortcuts.\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @returns {*}\n */\n function getIndex (arrayLike, index) {\n var idx = _getNaturalIndex(arrayLike, index);\n return isUndefined(idx) ? idx : arrayLike[idx];\n }\n\n /**\n * A curried version of {@link module:lamb.getIn|getIn}.
\n * Receives a property name and builds a function expecting the object from which we want to retrieve the property.\n * @example\n * var user1 = {name: \"john\"};\n * var user2 = {name: \"jane\"};\n * var getName = _.getKey(\"name\");\n *\n * getName(user1) // => \"john\"\n * getName(user2) // => \"jane\"\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getIn|getIn}\n * @see {@link module:lamb.getPath|getPath}, {@link module:lamb.getPathIn|getPathIn}\n * @param {String} key\n * @returns {Function}\n */\n function getKey (key) {\n return function (obj) {\n return getIn(obj, key);\n };\n }\n\n /**\n * Builds a partial application of {@link module:lamb.getPathIn|getPathIn} with the given\n * path and separator, expecting the object to act upon.
\n * @example\n * var user = {\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * \"user.name\": \"jdoe\",\n * password: \"abc123\"\n * }\n * };\n *\n * var getPwd = _.getPath(\"login.password\");\n * var getUsername = _.getPath(\"login/user.name\", \"/\");\n *\n * getPwd(user) // => \"abc123\";\n * getUsername(user) // => \"jdoe\"\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPathIn|getPathIn}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\n function getPath (path, separator) {\n return partial(getPathIn, _, path, separator);\n }\n\n /**\n * Gets a nested property value from an object using the given path.
\n * The path is a string with property names separated by dots by default, but\n * it can be customised with the optional third parameter.
\n * You can use integers in the path, even negative ones, to refer to array-like\n * object indexes, but the priority will be given to existing object keys:\n * the last example explains this particular case.\n * @example\n * var user = {\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * \"user.name\": \"jdoe\",\n * password: \"abc123\"\n * },\n * scores: [\n * {id: 1, value: 10},\n * {id: 2, value: 20},\n * {id: 3, value: 30}\n * ]\n * };\n *\n * _.getPathIn(user, \"name\") // => \"John\"\n * _.getPathIn(user, \"login.password\") // => \"abc123\";\n * _.getPathIn(user, \"login/user.name\", \"/\") // => \"jdoe\"\n * _.getPathIn(user, \"name.foo\") // => undefined\n * _.getPathIn(user, \"name.foo.bar\") // => undefined\n *\n * @example Accessing array-like objects indexes:\n * _.getPathIn(user, \"login.password.1\") // => \"b\"\n * _.getPathIn(user, \"scores.0\") // => {id: 1, value: 10}\n * _.getPathIn(user, \"scores.-1.value\") // => 30\n *\n * @example Priority will be given to existing object keys over indexes:\n * _.getPathIn(user, \"scores.-1\") // => {id: 3, value: 30}\n *\n * // let's do something funny\n * user.scores[\"-1\"] = \"foo bar\";\n *\n * _.getPathIn(user, \"scores.-1\") // => \"foo bar\";\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPath|getPath}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @param {Object|ArrayLike} obj\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {*}\n */\n function getPathIn (obj, path, separator) {\n if (isNil(obj)) {\n throw _makeTypeErrorFor(obj, \"object\");\n }\n\n var parts = _toPathParts(path, separator);\n var pathInfo = _getPathInfo(obj, parts, true);\n\n return pathInfo.target;\n }\n\n /**\n * Retrieves the first element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.head([1, 2, 3]) // => 1\n * _.head(\"hello\") // => \"h\"\n * _.head([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.last|last}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var head = getAt(0);\n\n /**\n * Retrieves the last element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.last([1, 2, 3]) // => 3\n * _.last(\"hello\") // => \"o\"\n * _.last([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.head|head}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var last = getAt(-1);\n\n /**\n * Builds a function that creates a copy of an array-like object with the given\n * index changed to the desired value.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.setAt(2, 99)(arr) // => [1, 2, 99, 4, 5]\n * arr // => [1, 2, 3, 4, 5]\n *\n * _.setAt(10, 99)(arr) // => [1, 2, 3, 4, 5] (not a reference to `arr`)\n *\n * @example Using negative indexes\n * _.setAt(-1, 99)(arr) // => [1, 2, 3, 4, 99]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.setIndex|setIndex}\n * @param {Number} index\n * @param {*} value\n * @returns {Function}\n */\n function setAt (index, value) {\n return function (arrayLike) {\n return _setIndex(arrayLike, index, value);\n };\n }\n\n /**\n * Sets the specified key to the given value in a copy of the provided object.
\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.
\n * If the specified key is not part of the source object, it will be added to the\n * result.
\n * The main purpose of the function is to work on simple plain objects used as\n * data structures, such as JSON objects, and makes no effort to play nice with\n * objects created from an OOP perspective (it's not worth it).
\n * For example the prototype of the result will be Object's regardless\n * of the source's one.\n * @example\n * var user = {name: \"John\", surname: \"Doe\", age: 30};\n *\n * _.setIn(user, \"name\", \"Jane\") // => {name: \"Jane\", surname: \"Doe\", age: 30}\n * _.setIn(user, \"gender\", \"male\") // => {name: \"John\", surname: \"Doe\", age: 30, gender: \"male\"}\n *\n * // `user` still is {name: \"John\", surname: \"Doe\", age: 30}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setKey|setKey}\n * @see {@link module:lamb.setPath|setPath}, {@link module:lamb.setPathIn|setPathIn}\n * @param {Object} source\n * @param {String} key\n * @param {*} value\n * @returns {Object}\n */\n function setIn (source, key, value) {\n return _merge(enumerables, source, make([key], [value]));\n }\n\n /**\n * Creates a copy of an array-like object with the given index changed to\n * the desired value.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [1, 2, 3];\n *\n * _.setIndex(arr, 1, 99) // => [1, 99, 3]\n * _.setIndex(arr, -1, 99) // => [1, 2, 99]\n * _.setIndex(arr, 10, 99) // => [1, 2, 3] (not a reference to `arr`)\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.setAt|setAt}\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} value\n * @returns {*}\n */\n var setIndex = aritize(_setIndex, 3);\n\n /**\n * Builds a partial application of {@link module:lamb.setIn|setIn} with the provided\n * key and value.
\n * The resulting function expects the object to act upon.
\n * Please refer to {@link module:lamb.setIn|setIn}'s description for explanations about\n * how the copy of the source object is made.\n * @example\n * var user = {name: \"John\", surname: \"Doe\", age: 30};\n * var setAgeTo40 = _.setKey(\"age\", 40);\n *\n * setAgeTo40(user) // => {name: \"john\", surname: \"doe\", age: 40}\n *\n * // `user` still is {name: \"John\", surname: \"Doe\", age: 30}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setIn|setIn}\n * @see {@link module:lamb.setPath|setPath}, {@link module:lamb.setPathIn|setPathIn}\n * @param {String} key\n * @param {*} value\n * @returns {Function}\n */\n function setKey (key, value) {\n return partial(setIn, _, key, value);\n }\n\n /**\n * Builds a partial application of {@link module:lamb.setPathIn|setPathIn} expecting the\n * object to act upon.
\n * See {@link module:lamb.setPathIn|setPathIn} for more details and examples.\n * @example\n * var user = {id: 1, status: {active: false}};\n * var activate = _.setPath(\"status.active\", true);\n *\n * activate(user) // => {id: 1, status: {active: true}}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setPathIn|setPathIn}\n * @see {@link module:lamb.setIn|setIn}, {@link module:lamb.setKey|setKey}\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\n function setPath (path, value, separator) {\n return partial(setPathIn, _, path, value, separator);\n }\n\n /**\n * Allows to change a nested value in a copy of the provided object.
\n * The function will delegate the \"set action\" to {@link module:lamb.setIn|setIn} or\n * {@link module:lamb.setAt|setAt} depending on the value encountered in the path,\n * so please refer to the documentation of those functions for specifics about the\n * implementation.
\n * Note anyway that the distinction will be between Arrays, delegated\n * to {@link module:lamb.setAt|setAt}, and everything else (including array-like objects),\n * which will be delegated to {@link module:lamb.setIn|setIn}.
\n * As a result of that, array-like objects will be converted to objects having numbers as keys\n * and paths targeting non-object values will be converted to empty objects.
\n * You can anyway target array elements using integers in the path, even negative ones, but\n * the priority will be given to existing, and enumerable, object keys.
\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.
\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * var user = {id: 1, status: {active : false, scores: [2, 4, 6]}};\n *\n * _.setPathIn(user, \"status.active\", true) // => {id: 1, status: {active : true, scores: [2, 4, 6]}}\n *\n * @example Targeting arrays\n * _.setPathIn(user, \"status.scores.0\", 8) // => {id: 1, status: {active : false, scores: [8, 4, 6]}}\n *\n * // you can use negative indexes as well\n * _.setPathIn(user, \"status.scores.-1\", 8) // => {id: 1, status: {active : false, scores: [2, 4, 8]}}\n *\n * @example Arrays can also be part of the path and not necessarily its target\n * var user = {id: 1, scores: [\n * {value: 2, year: \"2000\"},\n * {value: 4, year: \"2001\"},\n * {value: 6, year: \"2002\"}\n * ]};\n *\n * var newUser = _.setPathIn(user, \"scores.0.value\", 8);\n * // \"newUser\" holds:\n * // {id: 1, scores: [\n * // {value: 8, year: \"2000\"},\n * // {value: 4, year: \"2001\"},\n * // {value: 6, year: \"2002\"}\n * // ]}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.setPath|setPath}\n * @see {@link module:lamb.setIn|setIn}, {@link module:lamb.setKey|setKey}\n * @param {Object|Array} source\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Object|Array}\n */\n function setPathIn (source, path, value, separator) {\n if (isNil(source)) {\n throw _makeTypeErrorFor(source, \"object\");\n }\n\n return _setPathIn(source, _toPathParts(path, separator), value);\n }\n\n /**\n * Builds a function that creates a copy of an array-like object with the given index\n * changed by applying the provided function to its value.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [\"a\", \"b\", \"c\"];\n * var toUpperCase = _.invoker(\"toUpperCase\");\n *\n * _.updateAt(1, toUpperCase)(arr) // => [\"a\", \"B\", \"c\"]\n * _.updateAt(-1, toUpperCase)(arr) // => [\"a\", \"b\", \"C\"]\n * _.updateAt(10, toUpperCase)(arr) // => [\"a\", \"b\", \"c\"] (not a reference to `arr`)\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.updateIndex|updateIndex}\n * @param {Number} index\n * @param {Function} updater\n * @returns {Function}\n */\n function updateAt (index, updater) {\n return function (arrayLike) {\n return _setIndex(arrayLike, index, null, updater);\n };\n }\n\n /**\n * Creates a copy of the given object having the desired key value updated by applying\n * the provided function to it.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * var user = {name: \"John\", visits: 2};\n * var toUpperCase = _.invoker(\"toUpperCase\");\n *\n * _.updateIn(user, \"name\", toUpperCase) // => {name: \"JOHN\", visits: 2}\n * _.updateIn(user, \"surname\", toUpperCase) // => {name: \"John\", visits: 2}\n *\n * @example Non-enumerable properties will be treated as non-existent:\n * var user = Object.create({name: \"John\"}, {visits: {value: 2}});\n * var increment = _.partial(_.add, 1);\n *\n * _.updateIn(user, \"visits\", increment) // => {name: \"John\", visits: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updateKey|updateKey}\n * @see {@link module:lamb.updatePath|updatePath}, {@link module:lamb.updatePathIn|updatePathIn}\n * @param {Object} source\n * @param {String} key\n * @param {Function} updater\n * @returns {Object}\n */\n function updateIn (source, key, updater) {\n return _isEnumerable(source, key) ? setIn(source, key, updater(source[key])) : _merge(enumerables, source);\n }\n\n /**\n * Creates a copy of an array-like object with the given index changed by applying the\n * provided function to its value.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * var arr = [\"a\", \"b\", \"c\"];\n * var toUpperCase = _.invoker(\"toUpperCase\");\n *\n * _.updateIndex(arr, 1, toUpperCase) // => [\"a\", \"B\", \"c\"]\n * _.updateIndex(arr, -1, toUpperCase) // => [\"a\", \"b\", \"C\"]\n * _.updateIndex(arr, 10, toUpperCase) // => [\"a\", \"b\", \"c\"] (not a reference to `arr`)\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.updateAt|updateAt}\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {Function} updater\n * @returns {Array}\n */\n var updateIndex = partial(_setIndex, _, _, null, _);\n\n /**\n * Builds a partial application of {@link module:lamb.updateIn|updateIn} with the provided\n * key and updater, expecting the object to act upon.\n * @example\n * var user = {name: \"John\", visits: 2};\n * var increment = _.partial(_.add, 1);\n * var incrementVisits = _.updateKey(\"visits\", increment);\n *\n * incrementVisits(user) // => {name: \"John\", visits: 3}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updateIn|updateIn}\n * @see {@link module:lamb.updatePath|updatePath}, {@link module:lamb.updatePathIn|updatePathIn}\n * @param {String} key\n * @param {Function} updater\n * @returns {Function}\n */\n function updateKey (key, updater) {\n return partial(updateIn, _, key, updater);\n }\n\n /**\n * Builds a partial application of {@link module:lamb.updateIn|updateIn} expecting the object to act upon.\n * @example\n * var user = {id: 1, status: {scores: [2, 4, 6], visits: 0}};\n * var increment = _.partial(_.add, 1);\n * var incrementScores = _.updatePath(\"status.scores\", _.mapWith(increment))\n *\n * incrementScores(user) // => {id: 1, status: {scores: [3, 5, 7], visits: 0}}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updatePathIn|updatePathIn}\n * @see {@link module:lamb.updateIn|updateIn}, {@link module:lamb.updateKey|updateKey}\n * @param {String} path\n * @param {Function} updater\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\n function updatePath (path, updater, separator) {\n return partial(updatePathIn, _, path, updater, separator);\n }\n\n /**\n * Allows to change a nested value in a copy of the given object by applying the provided\n * function to it.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.
\n * @example\n * var user = {id: 1, status: {scores: [2, 4, 6], visits: 0}};\n * var increment = _.partial(_.add, 1);\n *\n * _.updatePathIn(user, \"status.visits\", increment) // => {id: 1, status: {scores: [2, 4, 6]}, visits: 1}\n *\n * @example Targeting arrays\n * _.updatePathIn(user, \"status.scores.0\", increment) // => {id: 1, status: {scores: [3, 4, 6], visits: 0}}\n *\n * // you can use negative indexes as well\n * _.updatePathIn(user, \"status.scores.-1\", increment) // => {id: 1, status: {scores: [2, 4, 7], visits: 0}}\n *\n * @example Arrays can also be part of the path and not necessarily its target\n * var user = {id: 1, scores: [\n * {value: 2, year: \"2000\"},\n * {value: 4, year: \"2001\"},\n * {value: 6, year: \"2002\"}\n * ]};\n *\n * var newUser = _.updatePathIn(user, \"scores.0.value\", increment);\n * // \"newUser\" holds:\n * // {id: 1, scores: [\n * // {value: 3, year: \"2000\"},\n * // {value: 4, year: \"2001\"},\n * // {value: 6, year: \"2002\"}\n * // ]}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.updatePath|updatePath}\n * @see {@link module:lamb.updateIn|updateIn}, {@link module:lamb.updateKey|updateKey}\n * @param {Object|Array} source\n * @param {String} path\n * @param {Function} updater\n * @param {String} [separator=\".\"]\n * @returns {Object|Array}\n */\n function updatePathIn (source, path, updater, separator) {\n var parts = _toPathParts(path, separator);\n var pathInfo = _getPathInfo(source, parts, false);\n\n if (pathInfo.isValid) {\n return _setPathIn(source, parts, updater(pathInfo.target));\n } else {\n return Array.isArray(source) ? slice(source) : _merge(enumerables, source);\n }\n }\n\n lamb.getAt = getAt;\n lamb.getIn = getIn;\n lamb.getIndex = getIndex;\n lamb.getKey = getKey;\n lamb.getPath = getPath;\n lamb.getPathIn = getPathIn;\n lamb.head = head;\n lamb.last = last;\n lamb.setAt = setAt;\n lamb.setIn = setIn;\n lamb.setIndex = setIndex;\n lamb.setKey = setKey;\n lamb.setPath = setPath;\n lamb.setPathIn = setPathIn;\n lamb.updateAt = updateAt;\n lamb.updateIn = updateIn;\n lamb.updateIndex = updateIndex;\n lamb.updateKey = updateKey;\n lamb.updatePath = updatePath;\n lamb.updatePathIn = updatePathIn;\n\n\n /**\n * Builds a predicate to check if an array-like object contains the given value.
\n * Please note that the equality test is made with {@link module:lamb.isSVZ|isSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * var containsNaN = _.contains(NaN, 0);\n *\n * containsNaN([0, 1, 2, 3, NaN]) // => true\n *\n * @memberof module:lamb\n * @category Array\n * @param {*} value\n * @param {Number} [fromIndex=0] The position at which to begin searching for the given value.\n * @returns {Function}\n */\n function contains (value, fromIndex) {\n return function (arrayLike) {\n return isIn(arrayLike, value, fromIndex);\n };\n }\n\n /**\n * Returns an array of items present only in the first of the given arrays.
\n * Note that since version 0.13.0 this function uses the [\"SameValueZero\" comparison]{@link module:lamb.isSVZ|isSVZ}.\n * @example\n * var a1 = [1, 2, 3, 4];\n * var a2 = [2, 4, 5];\n * var a3 = [4, 5, 3, 1];\n *\n * _.difference(a1, a2) // => [1, 3]\n * _.difference(a1, a2, a3) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @param {Array} array\n * @param {...Array} other\n * @returns {Array}\n */\n function difference (array) {\n var rest = shallowFlatten(map(slice(arguments, 1), unary(slice)));\n var isInRest = partial(isIn, rest, _, 0);\n return filter(array, not(isInRest));\n }\n\n /**\n * Builds an array without the first n elements of the given array or array-like object.\n * Note that, being this only a shortcut for a specific use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.drop(arr, 2) // => [3, 4, 5]\n * _.drop(arr, -1) // => [5]\n * _.drop(arr, -10) // => [1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {ArrayLike} arrayLike\n * @param {Number} n\n * @returns {Array}\n */\n var drop = binary(slice);\n\n /**\n * A curried version of {@link module:lamb.drop|drop} that expects the number of elements\n * to drop to build a function waiting for the list to take the elements from.\n * See the note and examples for {@link module:lamb.drop|drop} about passing a negative n.\n * @example\n * var drop2 = _.dropN(2);\n *\n * drop2([1, 2, 3, 4, 5]) // => [3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.drop|drop}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {Number} n\n * @returns {Function}\n */\n function dropN (n) {\n return function (arrayLike) {\n return slice(arrayLike, n);\n };\n }\n\n /**\n * Builds a function that drops the first n elements satisfying a predicate from an array or array-like object.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var dropWhileIsEven = _.dropWhile(isEven);\n *\n * dropWhileIsEven([2, 4, 6, 8]) // => []\n * dropWhileIsEven([2, 4, 7, 8]) // => [7, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.takeWhile|takeWhile}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n function dropWhile (predicate, predicateContext) {\n var fn = arguments.length === 2 ? _getNumConsecutiveHits : binary(_getNumConsecutiveHits);\n\n return function (arrayLike) {\n return slice(arrayLike, fn(arrayLike, predicate, predicateContext));\n };\n }\n\n /**\n * Searches for an element satisfying the predicate in the given array-like object and returns it if\n * the search is successful. Returns undefined otherwise.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 40}\n * ];\n *\n * _.find(persons, _.hasKeyValue(\"age\", 40)) // => {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40}\n * _.find(persons, _.hasKeyValue(\"age\", 41)) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {*}\n */\n function find (arrayLike, predicate, predicateContext) {\n var result;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0, len = arrayLike.length, element; i < len; i++) {\n element = arrayLike[i];\n\n if (predicate(element, i, arrayLike)) {\n result = element;\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Searches for an element satisfying the predicate in the given array-like object and returns its\n * index if the search is successful. Returns -1 otherwise.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 40}\n * ];\n *\n * _.findIndex(persons, _.hasKeyValue(\"age\", 40)) // => 1\n * _.findIndex(persons, _.hasKeyValue(\"age\", 41)) // => -1\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Number}\n */\n function findIndex (arrayLike, predicate, predicateContext) {\n var result = -1;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0, len = arrayLike.length; i < len; i++) {\n if (predicate(arrayLike[i], i, arrayLike)) {\n result = i;\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Similar to {@link module:lamb.map|map}, but if the mapping function returns an array this will\n * be concatenated, rather than pushed, to the final result.\n * @example showing the difference with map\n * var words = [\"foo\", \"bar\"];\n * var toCharArray = function (s) { return s.split(\"\"); };\n *\n * _.map(words, toCharArray) // => [[\"f\", \"o\", \"o\"], [\"b\", \"a\", \"r\"]]\n * _.flatMap(words, toCharArray) // => [\"f\", \"o\", \"o\", \"b\", \"a\", \"r\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.flatMapWith|flatMapWith}\n * @param {Array} array\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n var flatMap = compose(shallowFlatten, map);\n\n /**\n * Builds a partial application of {@link module:lamb.flatMap|flatMap} using the given iteratee\n * and the optional context. The resulting function expects the array to act upon.\n * @example\n * var toCharArray = function (s) { return s.split(\"\"); };\n * var wordsToCharArray = _.flatMapWith(toCharArray);\n *\n * wordsToCharArray([\"foo\", \"bar\"]) // => [\"f\", \"o\", \"o\", \"b\", \"a\", \"r\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.flatMap|flatMap}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var flatMapWith = _partialWithIteratee(flatMap);\n\n /**\n * Flattens an array.\n * @example showing the difference with shallowFlatten\n * var arr = [1, 2, [3, 4, [5, 6]], 7, 8];\n *\n * _.flatten(arr) // => [1, 2, 3, 4, 5, 6, 7, 8]\n * _.shallowFlatten(arr) // => [1, 2, 3, 4, [5, 6], 7, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.shallowFlatten|shallowFlatten}\n * @param {Array} array\n * @returns {Array}\n */\n function flatten (array) {\n return Array.isArray(array) ? _flatten(array, []) : slice(array);\n }\n\n /**\n * Returns a copy of the given array-like object without the last element.\n * @example\n * _.init([1, 2, 3, 4]) // => [1, 2, 3]\n * _.init([1]) // => []\n * _.init([]) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.tail|tail}\n * @see {@link module:lamb.head|head}, {@link module:lamb.last|last}\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\n var init = partial(slice, _, 0, -1);\n\n /**\n * Inserts the provided element in a copy of an array-like object at the\n * specified index.
\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.
\n * Negative indexes are allowed; when a negative index is out of bounds\n * the element will be inserted at the start of the resulting array.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.insert(arr, 3, 99) // => [1, 2, 3, 99, 4, 5]\n * _.insert(arr, -2, 99) // => [1, 2, 3, 99, 4, 5]\n * _.insert(arr, 10, 99) // => [1, 2, 3, 4, 5, 99]\n * _.insert(arr, -10, 99) // => [99, 1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.insertAt|insertAt}\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} element\n * @returns {Array}\n */\n function insert (arrayLike, index, element) {\n var result = slice(arrayLike);\n result.splice(index, 0, element);\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.insert|insert}\n * expecting the array-like object to act upon.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.insertAt(3, 99)(arr) // => [1, 2, 3, 99, 4, 5]\n * _.insertAt(-2, 99)(arr) // => [1, 2, 3, 99, 4, 5]\n * _.insertAt(10, 99)(arr) // => [1, 2, 3, 4, 5, 99]\n * _.insertAt(-10, 99)(arr) // => [99, 1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.insert|insert}\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @param {Number} index\n * @param {*} element\n * @returns {Function}\n */\n function insertAt (index, element) {\n return partial(insert, _, index, element);\n }\n\n /**\n * Returns an array of every item present in all given arrays.
\n * Note that since version 0.13.0 this function uses the [\"SameValueZero\" comparison]{@link module:lamb.isSVZ|isSVZ}.\n * @example\n * var a1 = [1, 2, 3, 4];\n * var a2 = [2, 5, 4, 6];\n * var a3 = [5, 6, 7];\n *\n * _.intersection(a1, a2) // => [2, 4]\n * _.intersection(a1, a3) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @param {...Array} array\n * @return {Array}\n */\n function intersection () {\n var rest = slice(arguments, 1);\n\n return filter(uniques(arguments[0]), function (item) {\n return rest.every(contains(item));\n });\n }\n\n /**\n * Checks if an array-like object contains the given value.
\n * Please note that the equality test is made with {@link module:lamb.isSVZ|isSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * var numbers = [0, 1, 2, 3, NaN];\n *\n * _.isIn(numbers, 1) // => true\n * _.isIn(numbers, 0) // => true\n * _.isIn(numbers, -0) // => true\n * _.isIn(numbers, NaN) // => true\n * _.isIn(numbers, 2, 3) // => false\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {*} value\n * @param {Number} [fromIndex=0] The position at which to begin searching for the given value.\n * @returns {Boolean}\n */\n function isIn (arrayLike, value, fromIndex) {\n var result = false;\n\n for (var i = fromIndex >>> 0, len = arrayLike.length; i < len; i++) {\n if (isSVZ(value, arrayLike[i])) {\n result = true;\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Generates an array with the values passed as arguments.\n * @example\n * _.list(1, 2, 3) // => [1, 2, 3]\n *\n * @memberof module:lamb\n * @category Array\n * @param {...*} value\n * @returns {Array}\n */\n function list () {\n var len = arguments.length;\n var result = Array(len);\n\n for (var i = 0; i < len; i++) {\n result[i] = arguments[i];\n }\n\n return result;\n }\n\n /**\n * Splits an array-like object in two lists: the first with the elements satisfying the given predicate,\n * the others with the remaining elements.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n *\n * _.partition(numbers, isEven) // => [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.partitionWith|partitionWith}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Array, Array<*>>}\n */\n function partition (arrayLike, predicate, predicateContext) {\n var result = [[], []];\n var len = arrayLike.length;\n\n if (arguments.length === 3) {\n predicate = predicate.bind(predicateContext);\n }\n\n for (var i = 0, el; i < len; i++) {\n el = arrayLike[i];\n result[predicate(el, i, arrayLike) ? 0 : 1].push(el);\n }\n\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.partition|partition} using the given predicate and the optional context.\n * The resulting function expects the array-like object to act upon.\n * @example\n * var users = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"active\": false},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"active\": true},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"active\": true},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"active\": false}\n * ];\n * var isActive = _.hasKeyValue(\"active\", true);\n * var splitByActiveStatus = _.partitionWith(isActive);\n *\n * splitByActiveStatus(users) // =>\n * // [[\n * // {\"name\": \"John\", \"surname\": \"Doe\", \"active\": true},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\", \"active\": true}\n * // ], [\n * // {\"name\": \"Jane\", \"surname\": \"Doe\", \"active\": false},\n * // {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"active\": false}\n * // ]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.partition|partition}\n * @param {ListIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n var partitionWith = _partialWithIteratee(partition);\n\n /**\n * \"Plucks\" the values of the specified key from a list of objects.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 15}\n * ];\n *\n * _.pluck(persons, \"age\") // => [12, 40, 18, 15]\n *\n * var lists = [\n * [1, 2],\n * [3, 4, 5],\n * [6]\n * ];\n *\n * _.pluck(lists, \"length\") // => [2, 3, 1]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.pluckKey|pluckKey}\n * @param {ArrayLike} arrayLike\n * @param {String} key\n * @returns {Array}\n */\n function pluck (arrayLike, key) {\n return map(arrayLike, getKey(key));\n }\n\n /**\n * A curried version of {@link module:lamb.pluck|pluck} expecting the key to retrieve to\n * build a function waiting for the array-like object to act upon.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"surname\": \"Doe\", \"age\": 12},\n * {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\", \"age\": 18},\n * {\"name\": \"Paolo\", \"surname\": \"Bianchi\", \"age\": 15}\n * ];\n * var getAges = _.pluckKey(\"age\");\n *\n * getAges(persons) // => [12, 40, 18, 15]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.pluck|pluck}\n * @function\n * @param {String} key\n * @returns {Function}\n */\n var pluckKey = compose(mapWith, getKey);\n\n /**\n * Reverses a copy of the given array-like object.\n * @example\n * var arr = [1, 2, 3];\n *\n * _.reverse(arr) // => [3, 2, 1];\n *\n * // `arr` still is [1, 2, 3]\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\n function reverse (arrayLike) {\n return slice(arrayLike).reverse();\n }\n\n /**\n * Flattens the \"first level\" of an array.\n * @example showing the difference with flatten\n * var arr = [1, 2, [3, 4, [5, 6]], 7, 8];\n *\n * _.flatten(arr) // => [1, 2, 3, 4, 5, 6, 7, 8]\n * _.shallowFlatten(arr) // => [1, 2, 3, 4, [5, 6], 7, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.flatten|flatten}\n * @param {Array} array\n * @returns {Array}\n */\n function shallowFlatten (array) {\n return Array.isArray(array) ? _arrayProto.concat.apply([], array) : slice(array);\n }\n\n /**\n * Returns a copy of the given array-like object without the first element.\n * @example\n * _.tail([1, 2, 3, 4]) // => [2, 3, 4]\n * _.tail([1]) // => []\n * _.tail([]) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.init|init}\n * @see {@link module:lamb.head|head}, {@link module:lamb.last|last}\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\n var tail = partial(slice, _, 1, void 0);\n\n /**\n * Retrieves the first n elements from an array or array-like object.
\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * var arr = [1, 2, 3, 4, 5];\n *\n * _.take(arr, 3) // => [1, 2, 3]\n * _.take(arr, -1) // => [1, 2, 3, 4]\n * _.take(arr, -10) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {ArrayLike} arrayLike\n * @param {Number} n\n * @returns {Array}\n */\n function take (arrayLike, n) {\n return slice(arrayLike, 0, +n);\n }\n\n /**\n * A curried version of {@link module:lamb.take|take} that expects the number of elements\n * to retrieve to build a function waiting for the list to take the elements from.\n * See the note and examples for {@link module:lamb.take|take} about passing a negative n.\n * @example\n * var take2 = _.takeN(2);\n *\n * take2([1, 2, 3, 4, 5]) // => [1, 2]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.take|take}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @param {Number} n\n * @returns {Function}\n */\n function takeN (n) {\n return function (arrayLike) {\n return slice(arrayLike, 0, +n);\n };\n }\n\n /**\n * Builds a function that takes the first n elements satisfying a predicate from an array or array-like object.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var takeWhileIsEven = _.takeWhile(isEven);\n *\n * takeWhileIsEven([1, 2, 4, 6, 8]) // => []\n * takeWhileIsEven([2, 4, 7, 8]) // => [2, 4]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.take|take}, {@link module:lamb.takeN|takeN}\n * @see {@link module:lamb.drop|drop}, {@link module:lamb.dropN|dropN}\n * @param {ListIteratorCallback} predicate\n * @param {Object} predicateContext\n * @returns {Function}\n */\n function takeWhile (predicate, predicateContext) {\n var fn = arguments.length === 2 ? _getNumConsecutiveHits : binary(_getNumConsecutiveHits);\n\n return function (arrayLike) {\n return slice(arrayLike, 0, fn(arrayLike, predicate, predicateContext));\n };\n }\n\n /**\n * Transposes a matrix. Can also be used to reverse a {@link module:lamb.zip|zip} operation.
\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example transposing a matrix\n * _.transpose([\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ]) // =>\n * // [\n * // [1, 4, 7],\n * // [2, 5, 8],\n * // [3, 6, 9]\n * // ]\n *\n * @example showing the relationship with zip\n * var zipped = _.zip([\"a\", \"b\", \"c\"], [1, 2, 3]); // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\n *\n * _.transpose(zipped) // => [[\"a\", \"b\", \"c\"], [1, 2, 3]]\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike>} arrayLike\n * @returns {Array>}\n */\n function transpose (arrayLike) {\n var result = [];\n var minLen = Math.min.apply(null, pluck(arrayLike, \"length\")) >>> 0;\n var len = arrayLike.length;\n\n for (var i = 0, j; i < minLen; i++) {\n result.push([]);\n\n for (j = 0; j < len; j++) {\n result[i][j] = arrayLike[j][i];\n }\n }\n\n return result;\n }\n\n /**\n * Returns a list of every unique element present in the given array-like objects.\n * @example\n * _.union([1, 2, 3, 2], [3, 4], [1, 5]) // => [1, 2, 3, 4, 5]\n * _.union(\"abc\", \"bcd\", \"cde\") // => [\"a\", \"b\", \"c\", \"d\", \"e\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {...ArrayLike} arrayLike\n * @returns {Array}\n */\n var union = compose(uniques, flatMapWith(unary(slice)), list);\n\n /**\n * Returns an array comprised of the unique elements of the given array-like object.
\n * Can work with lists of complex objects if supplied with an iteratee.
\n * Note that since version 0.13.0 this function uses the [\"SameValueZero\" comparison]{@link module:lamb.isSVZ|isSVZ}.\n * @example with simple values\n * _.uniques([1, 2, 2, 3, 4, 3, 5, 1]) // => [1, 2, 3, 4, 5]\n *\n * @example with complex values\n * var data = [\n * {id: \"1\"},\n * {id: \"4\"},\n * {id: \"5\"},\n * {id: \"1\"},\n * {id: \"5\"},\n * ];\n *\n * _.uniques(data, _.getKey(\"id\")) // => [{id: \"1\"}, {id: \"4\"}, {\"id\": 5}]\n *\n * @memberof module:lamb\n * @category Array\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} [iteratee] Defaults to the [identity function]{@link module:lamb.identity}.\n * @param {Object} [iterateeContext]\n * @returns {Array}\n */\n function uniques (arrayLike, iteratee, iterateeContext) {\n if (typeof iteratee !== \"function\") {\n iteratee = identity;\n }\n\n if (arguments.length === 3) {\n iteratee = iteratee.bind(iterateeContext);\n }\n\n var result = [];\n var seen = [];\n var value;\n\n for (var i = 0, len = arrayLike.length; i < len; i++) {\n value = iteratee(arrayLike[i], i, arrayLike);\n\n if (!isIn(seen, value)) {\n seen.push(value);\n result.push(arrayLike[i]);\n }\n }\n\n return result;\n }\n\n /**\n * Builds a list of arrays out of the given array-like objects by pairing items with the same index.
\n * The received array-like objects will be truncated to the shortest length.
\n * See also {@link module:lamb.zipWithIndex|zipWithIndex} and {@link module:lamb.transpose|transpose} for the reverse operation.\n * @example\n * _.zip(\n * [\"a\", \"b\", \"c\"],\n * [1, 2, 3],\n * [true, false, true]\n * ) // => [[\"a\", 1, true], [\"b\", 2, false], [\"c\", 3, true]]\n *\n * _.zip([1, 2, 3, 4], [5, 6, 7]) // => [[1, 5], [2, 6], [3, 7]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {...ArrayLike} arrayLike\n * @returns {Array>}\n */\n var zip = compose(transpose, list);\n\n /**\n * \"{@link module:lamb.zip|Zips}\" an array-like object by pairing its values with their index.\n * @example\n * _.zipWithIndex([\"a\", \"b\", \"c\"]) // => [[\"a\", 0], [\"b\", 1], [\"c\", 2]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @param {ArrayLike} arrayLike\n * @returns {Array>}\n */\n var zipWithIndex = mapWith(binary(list));\n\n lamb.contains = contains;\n lamb.difference = difference;\n lamb.drop = drop;\n lamb.dropN = dropN;\n lamb.dropWhile = dropWhile;\n lamb.find = find;\n lamb.findIndex = findIndex;\n lamb.flatMap = flatMap;\n lamb.flatMapWith = flatMapWith;\n lamb.flatten = flatten;\n lamb.init = init;\n lamb.insert = insert;\n lamb.insertAt = insertAt;\n lamb.intersection = intersection;\n lamb.isIn = isIn;\n lamb.list = list;\n lamb.partition = partition;\n lamb.partitionWith = partitionWith;\n lamb.pluck = pluck;\n lamb.pluckKey = pluckKey;\n lamb.reverse = reverse;\n lamb.shallowFlatten = shallowFlatten;\n lamb.tail = tail;\n lamb.take = take;\n lamb.takeN = takeN;\n lamb.takeWhile = takeWhile;\n lamb.transpose = transpose;\n lamb.union = union;\n lamb.uniques = uniques;\n lamb.zip = zip;\n lamb.zipWithIndex = zipWithIndex;\n\n\n /**\n * Transforms an array-like object in a lookup table with the keys generated by the provided\n * iteratee, having as values the count of matches for the key.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"age\": 12},\n * {\"name\": \"John\", \"age\": 40},\n * {\"name\": \"Mario\", \"age\": 17},\n * {\"name\": \"Paolo\", \"age\": 15}\n * ];\n * var getAgeStatus = function (person) { return person.age >= 18 ? \"adult\" : \"minor\"; };\n *\n * _.count(persons, getAgeStatus) // => {\"adult\": 1, \"minor\": 3}\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Object}\n */\n var count = _groupWith(partial(add, 1), 0);\n\n /**\n * Using the provided iteratee, and its optional context, builds a partial application of\n * {@link module:lamb.count|count} expecting the array-like object to act upon.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"city\": \"New York\"},\n * {\"name\": \"John\", \"city\": \"New York\"},\n * {\"name\": \"Mario\", \"city\": \"Rome\"},\n * {\"name\": \"Paolo\"}\n * ];\n * var getCityOrUnknown = _.adapter(_.getKey(\"city\"), _.always(\"Unknown\"));\n * var countByCity = _.countBy(getCityOrUnknown);\n *\n * countByCity(persons) // => {\"New York\": 2, \"Rome\": 1, \"Unknown\": 1}\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.count|count}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var countBy = _partialWithIteratee(count);\n\n /**\n * Transforms an array-like object into a lookup table using the provided iteratee as a grouping\n * criterion to generate keys and values.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"city\": \"New York\"},\n * {\"name\": \"John\", \"city\": \"New York\"},\n * {\"name\": \"Mario\", \"city\": \"Rome\"},\n * {\"name\": \"Paolo\"}\n * ];\n * var getCity = _.getKey(\"city\");\n * var personsByCity = _.group(persons, getCity);\n *\n * // \"personsByCity\" holds:\n * // {\n * // \"New York\": [\n * // {\"name\": \"Jane\", \"city\": \"New York\"},\n * // {\"name\": \"John\", \"city\": \"New York\"}\n * // ],\n * // \"Rome\": [\n * // {\"name\": \"Mario\", \"city\": \"Rome\"}\n * // ],\n * // \"undefined\": [\n * // {\"name\": \"Paolo\"}\n * // ]\n * // }\n *\n * @example Adding a custom value for missing keys\n *\n * var getCityOrUnknown = _.adapter(getCity, _.always(\"Unknown\"));\n *\n * var personsByCity = _.group(persons, getCityOrUnknown);\n *\n * // \"personsByCity\" holds:\n * // {\n * // \"New York\": [\n * // {\"name\": \"Jane\", \"city\": \"New York\"},\n * // {\"name\": \"John\", \"city\": \"New York\"}\n * // ],\n * // \"Rome\": [\n * // {\"name\": \"Mario\", \"city\": \"Rome\"}\n * // ],\n * // \"Unknown\": [\n * // {\"name\": \"Paolo\"}\n * // ]\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.groupBy|groupBy}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Object}\n */\n var group = _groupWith(invoker(\"concat\"), []);\n\n /**\n * Using the provided iteratee, and its optional context, builds a partial application\n * of {@link module:lamb.group|group} expecting the array-like object to act upon.\n * @example\n * var persons = [\n * {\"name\": \"Jane\", \"age\": 12},\n * {\"name\": \"John\", \"age\": 40},\n * {\"name\": \"Mario\", \"age\": 18},\n * {\"name\": \"Paolo\", \"age\": 15}\n * ];\n *\n * var getAgeStatus = function (person) { return person.age > 20 ? \"over 20\" : \"under 20\"; };\n * var groupByAgeStatus = _.groupBy(getAgeStatus);\n *\n * var personsByAgeStatus = groupByAgeStatus(persons);\n *\n * // \"personsByAgeStatus\" holds:\n * // {\n * // \"under 20\": [\n * // {\"name\": \"Jane\", \"age\": 12},\n * // {\"name\": \"Mario\", \"age\": 18},\n * // {\"name\": \"Paolo\", \"age\": 15}\n * // ],\n * // \"over 20\": [\n * // {\"name\": \"John\", \"age\": 40}\n * // ]\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.group|group}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.index|index}, {@link module:lamb.indexBy|indexBy}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var groupBy = _partialWithIteratee(group);\n\n /**\n * Similar to {@link module:lamb.group|group}, but the generated lookup table will have\n * only one element of the original array-like object for each value.
\n * Should be used only when you're sure that your iteratee won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * var users = [\n * {id: 1, name: \"John\"},\n * {id: 2, name: \"Jane\"},\n * {id: 3, name: \"Mario\"},\n * {id: 4, name: \"John\"}\n * ];\n *\n * var indexedUsers = _.index(users, _.getKey(\"id\"));\n *\n * // \"indexedUsers\" holds:\n * // {\n * // \"1\": {id: 1, name: \"John\"},\n * // \"2\": {id: 2, name: \"Jane\"},\n * // \"3\": {id: 3, name: \"Mario\"},\n * // \"4\": {id: 4, name: \"John\"}\n * // }\n *\n * @example Result of an iteratee producing a duplicate key:\n * var users = [\n * {id: 1, name: \"John\"},\n * {id: 2, name: \"Jane\"},\n * {id: 3, name: \"Mario\"},\n * {id: 4, name: \"John\"}\n * ];\n *\n * var indexedUsers = _.index(users, _.getKey(\"name\"));\n *\n * // \"indexedUsers\" holds:\n * // {\n * // \"John\": {\"id\": 4, \"name\": \"John\"},\n * // \"Jane\": {\"id\": 2, \"name\": \"Jane\"},\n * // \"Mario\": {\"id\": 3, \"name\": \"Mario\"}\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.indexBy|indexBy}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Object}\n */\n var index = _groupWith(getArgAt(1));\n\n /**\n * Using the provided iteratee, and its optional context, builds a partial application\n * of {@link module:lamb.index|index} expecting the array-like object to act upon.\n * @example\n * var users = [\n * {id: 1, name: \"John\"},\n * {id: 2, name: \"Jane\"},\n * {id: 3, name: \"Mario\"}\n * ];\n * var indexByID = _.indexBy(_.getKey(\"id\"));\n *\n * var indexedUsers = indexByID(users);\n *\n * // \"indexedUsers\" holds:\n * // {\n * // \"1\": {id: 1, name: \"John\"},\n * // \"2\": {id: 2, name: \"Jane\"},\n * // \"3\": {id: 3, name: \"Mario\"}\n * // }\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.index|index}\n * @see {@link module:lamb.count|count}, {@link module:lamb.countBy|countBy}\n * @see {@link module:lamb.group|group}, {@link module:lamb.groupBy|groupBy}\n * @param {ListIteratorCallback} iteratee\n * @param {Object} [iterateeContext]\n * @returns {Function}\n */\n var indexBy = _partialWithIteratee(index);\n\n lamb.count = count;\n lamb.countBy = countBy;\n lamb.group = group;\n lamb.groupBy = groupBy;\n lamb.index = index;\n lamb.indexBy = indexBy;\n\n\n /**\n * Returns a [stably]{@link https://en.wikipedia.org/wiki/Sorting_algorithm#Stability} sorted copy of an\n * array-like object using the given criteria.
\n * Sorting criteria are built using Lamb's {@link module:lamb.sorter|sorter} function, but you can also\n * pass simple \"reader\" functions and default ascending sorters will be built for you.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in the comparison.
\n * Please note that if the arguments received by the default comparer aren't of the same type, they will be compared as strings.\n *\n * @example Stable sort:\n * var persons = [\n * {\"name\": \"John\", \"surname\" :\"Doe\"},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\"},\n * {\"name\": \"John\", \"surname\" :\"Moe\"},\n * {\"name\": \"Jane\", \"surname\": \"Foe\"}\n * ];\n *\n * var personsByName = _.sort(persons, _.getKey(\"name\"));\n *\n * // personsByName holds:\n * // [\n * // {\"name\": \"Jane\", \"surname\": \"Foe\"},\n * // {\"name\": \"John\", \"surname\" :\"Doe\"},\n * // {\"name\": \"John\", \"surname\" :\"Moe\"},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @example Stable multi-sort:\n * var personsByNameAscSurnameDesc = _.sort(\n * persons,\n * _.getKey(\"name\"),\n * _.sorterDesc(_.getKey(\"surname\"))\n * );\n *\n * // personsByNameAscSurnameDesc holds:\n * // [\n * // {\"name\": \"Jane\", \"surname\": \"Foe\"},\n * // {\"name\": \"John\", \"surname\" :\"Moe\"},\n * // {\"name\": \"John\", \"surname\" :\"Doe\"},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @example Using custom comparers:\n * var localeSorter = new Intl.Collator(\"it\");\n * var chars = [\"a\", \"è\", \"à\", \"é\", \"c\", \"b\", \"e\"];\n *\n * _.sort(chars, localeSorter) // => [\"a\", \"à\", \"b\", \"c\", \"e\", \"é\", \"è\"]\n *\n * var localeSorterDesc = _.sorterDesc(_.identity, localeSorter.compare);\n *\n * _.sort(chars, localeSorterDesc) // => [\"è\", \"é\", \"e\", \"c\", \"b\", \"à\", \"a\"]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @param {ArrayLike} arrayLike\n * @param {...(Sorter|Function)} [sorter={@link module:lamb.sorter|sorter()}]\n * @returns {Array}\n */\n function sort (arrayLike) {\n var criteria = _makeCriteria(slice(arguments, 1));\n var data = [];\n var result = [];\n var len = arrayLike.length;\n\n for (var i = 0; i < len; i++) {\n data.push({\n value: arrayLike[i],\n index: i\n });\n }\n\n data.sort(_compareWith(criteria));\n\n for (i = 0; i < len; i++) {\n result.push(data[i].value);\n }\n\n return result;\n }\n\n /**\n * Inserts an element in a copy of a sorted array respecting the sort order.\n * @example with simple values\n * _.sortedInsert([], 1) // => [1]\n * _.sortedInsert([2, 4, 6], 5) // => [2, 4, 5, 6]\n * _.sortedInsert([4, 2, 1], 3, _.sorterDesc()) // => [4, 3, 2, 1]\n *\n * @example with complex values\n * var persons = [\n * {\"name\": \"jane\", \"surname\": \"doe\"},\n * {\"name\": \"John\", \"surname\": \"Doe\"},\n * {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * ];\n *\n * var getLowerCaseName = _.compose(\n * _.invoker(\"toLowerCase\"),\n * _.getKey(\"name\")\n * );\n *\n * var result = _.sortedInsert(\n * persons,\n * {\"name\": \"marco\", \"surname\": \"Rossi\"},\n * getLowerCaseName\n * );\n *\n * // `result` holds:\n * // [\n * // {\"name\": \"jane\", \"surname\": \"doe\"},\n * // {\"name\": \"John\", \"surname\": \"Doe\"},\n * // {\"name\": \"marco\", \"surname\": \"Rossi\"},\n * // {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @see {@link module:lamb.insert|insert}, {@link module:lamb.insertAt|insertAt} to insert the element at a specific index\n * @param {ArrayLike} arrayLike\n * @param {*} element\n * @param {...(Sorter|Function)} [sorter={@link module:lamb.sorter|sorter()}] - The sorting criteria used to sort the array.\n * @returns {Array}\n */\n function sortedInsert (arrayLike, element) {\n var criteria = _makeCriteria(slice(arguments, 2));\n var result = slice(arrayLike);\n var idx = _getInsertionIndex(result, element, _compareWith(criteria), 0, result.length);\n\n result.splice(idx, 0, element);\n return result;\n }\n\n /**\n * Creates an ascending sort criterion with the provided reader and comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorterDesc|sorterDesc}\n * @param {Function} [reader={@link module:lamb.identity|identity}] A function meant to generate a simple value from a complex one. The function should evaluate the array element and supply the value to be passed to the comparer.\n * @param {Function} [comparer] An optional custom comparer function.\n * @returns {Sorter}\n */\n var sorter = partial(_sorter, _, false, _);\n\n /**\n * Creates a descending sort criterion with the provided reader and comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}\n * @param {Function} [reader={@link module:lamb.identity|identity}] A function meant to generate a simple value from a complex one. The function should evaluate the array element and supply the value to be passed to the comparer.\n * @param {Function} [comparer] An optional custom comparer function.\n * @returns {Sorter}\n */\n var sorterDesc = partial(_sorter, _, true, _);\n\n /**\n * Builds a partial application of {@link module:lamb.sort|sort} using the provided criteria. The returned\n * function expects the array-like object to sort.\n * As usual, sorting criteria are built using Lamb's {@link module:lamb.sorter|sorter} function, but you can also\n * pass simple \"reader\" functions and default ascending sorters will be built.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in the comparison.
\n * See {@link module:lamb.sort|sort} for more examples.\n *\n * @example\n * var sortAsNumbers = _.sortWith(parseFloat);\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * sortAsNumbers(weights) // => [\"1 Kg\", \"2 Kg\", \"7 Kg\", \"10 Kg\"]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sort|sort}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @param {...(Sorter|Function)} [sorter={@link module:lamb.sorter|sorter()}]\n * @returns {Function}\n */\n function sortWith () {\n var sorters = slice(arguments);\n\n return function (arrayLike) {\n return sort.apply(null, [arrayLike].concat(sorters));\n };\n }\n\n lamb.sort = sort;\n lamb.sortedInsert = sortedInsert;\n lamb.sorter = sorter;\n lamb.sorterDesc = sorterDesc;\n lamb.sortWith = sortWith;\n\n\n /**\n * Applies the passed function to the given argument list.\n * @example\n * _.apply(_.add, [3, 4]) // => 7\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {ArrayLike} args\n * @returns {*}\n */\n function apply (fn, args) {\n return fn.apply(this, Object(args));\n }\n\n /**\n * A curried version of {@link module:lamb.apply|apply}. Expects an array-like object to use as arguments\n * and builds a function waiting for the target of the application.\n * @example\n * var data = [3, 4];\n * var applyDataTo = _.applyArgs(data);\n *\n * applyDataTo(_.add) // => 7\n * applyDataTo(_.multiply) // => 12\n *\n * @memberof module:lamb\n * @category Function\n * @param {ArrayLike} args\n * @returns {Function}\n */\n function applyArgs (args) {\n return function (fn) {\n return fn.apply(this, Object(args));\n };\n }\n\n /**\n * Builds a function that passes only the specified amount of arguments to the given function.
\n * As {@link module:lamb.slice|slice} is used to extract the arguments, you can also\n * pass a negative arity.
\n * See also {@link module:lamb.binary|binary} and {@link module:lamb.unary|unary} for common use\n * cases shortcuts.\n * @example\n * function maxArgument () {\n * return Math.max.apply(null, arguments);\n * }\n *\n * maxArgument(10, 11, 45, 99) // => 99\n * _.aritize(maxArgument, 2)(10, 11, 45, 99) // => 11\n *\n * @example Using a negative arity:\n * _.aritize(maxArgument, -1)(10, 11, 45, 99) // => 45\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} arity\n * @returns {Function}\n */\n function aritize (fn, arity) {\n return function () {\n var args = slice(arguments, 0, arity);\n var argsLen = args.length;\n var n = Math.floor(arity);\n\n if (n > 0 && argsLen < n) {\n args = args.concat(Array(n - argsLen));\n }\n\n return fn.apply(this, args);\n };\n }\n\n /**\n * Builds a function that passes only two arguments to the given function.
\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.
\n * See also {@link module:lamb.unary|unary}.\n * @example\n * _.list(1, 2, 3, 4, 5) // => [1, 2, 3, 4, 5]\n * _.binary(_.list)(1, 2, 3, 4, 5) // => [1, 2]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @returns {Function}\n */\n function binary (fn) {\n return function (a, b) {\n return fn.call(this, a, b);\n };\n }\n\n /**\n * Accepts a series of functions and builds a new function. The functions in the series\n * will then be applied, in order, with the values received by the function built with\n * collect.
\n * The collected results will be returned in an array.\n * @example\n * var user = {\n * id: \"jdoe\",\n * name: \"John\",\n * surname: \"Doe\",\n * scores: [2, 4, 7]\n * };\n * var getIDAndLastScore = _.collect(_.getKey(\"id\"), _.getPath(\"scores.-1\"));\n *\n * getIDAndLastScore(user) // => [\"jdoe\", 7]\n *\n * @example\n * var minAndMax = _.collect(Math.min, Math.max);\n *\n * minAndMax(3, 1, -2, 5, 4, -1) // => [-2, 5]\n *\n * @memberof module:lamb\n * @category Function\n * @param {...Function} fn\n * @returns {Function}\n */\n function collect () {\n var functions = slice(arguments);\n\n return function () {\n return map(functions, applyArgs(arguments));\n };\n }\n\n /**\n * Transforms the evaluation of the given function in the evaluation of a sequence of functions\n * expecting only one argument. Each function of the sequence is a partial application of the\n * original one, which will be applied when the specified (or derived) arity is consumed.
\n * Currying will start from the leftmost argument: use {@link module:lamb.curryRight|curryRight}\n * for right currying.
\n * See also {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * and {@link module:lamb.partial|partial}.\n * @example\n * var multiplyBy = _.curry(_.multiply);\n * var multiplyBy10 = multiplyBy(10);\n *\n * multiplyBy10(5) // => 50\n * multiplyBy10(2) // => 20\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curry (fn, arity) {\n return _curry(fn, arity, false);\n }\n\n /**\n * Builds an auto-curried function. The resulting function can be called multiple times with\n * any number of arguments, and the original function will be applied only when the specified\n * (or derived) arity is consumed.
\n * Currying will start from the leftmost argument: use {@link module:lamb.curryableRight|curryableRight}\n * for right currying.
\n * See also {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight} and\n * {@link module:lamb.partial|partial}.\n * @example\n * var collectFourElements = _.curryable(_.list, 4);\n *\n * collectFourElements(2)(3)(4)(5) // => [2, 3, 4, 5]\n * collectFourElements(2)(3, 4)(5) // => [2, 3, 4, 5]\n * collectFourElements(2, 3, 4, 5) // => [2, 3, 4, 5]\n * collectFourElements(2, 3)(4, 5) // => [2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curryable (fn, arity) {\n return _curry(fn, arity, false, true);\n }\n\n /**\n * Same as {@link module:lamb.curryable|curryable}, but currying starts from the rightmost argument.\n * @example\n * var collectFourElements = _.curryableRight(_.list, 4);\n *\n * collectFourElements(2)(3)(4)(5) // => [5, 4, 3, 2]\n * collectFourElements(2)(3, 4)(5) // => [5, 4, 3, 2]\n * collectFourElements(2, 3, 4, 5) // => [5, 4, 3, 2]\n * collectFourElements(2, 3)(4, 5) // => [5, 4, 3, 2]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curryableRight (fn, arity) {\n return _curry(fn, arity, true, true);\n }\n\n /**\n * Same as {@link module:lamb.curry|curry}, but currying starts from the rightmost argument.\n * @example\n * var divideBy = _.curryRight(_.divide);\n * var halve = divideBy(2);\n * halve(3) // => 1.5\n * halve(3, 7) // => 1.5\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\n function curryRight (fn, arity) {\n return _curry(fn, arity, true);\n }\n\n /**\n * Returns a function that will execute the given function only if it stops being called for the specified timespan.
\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call happens immediately.\n * @example A common use case of debounce in a browser environment\n * var updateLayout = function () {\n * // some heavy DOM operations here\n * };\n *\n * window.addEventListener(\"resize\", _.debounce(updateLayout, 200), false);\n *\n * // The resize event is fired repeteadly until the user stops resizing the\n * // window, while the `updateLayout` function is called only once: 200 ms\n * // after he stopped.\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} timespan - Expressed in milliseconds\n * @returns {Function}\n */\n function debounce (fn, timespan) {\n var timeoutID;\n\n return function () {\n var context = this;\n var args = arguments;\n var debounced = function () {\n timeoutID = null;\n fn.apply(context, args);\n };\n\n clearTimeout(timeoutID);\n timeoutID = setTimeout(debounced, timespan);\n };\n }\n\n /**\n * Returns a function that applies its arguments to the original function in reverse order.\n * @example\n * _.list(1, 2, 3) // => [1, 2, 3]\n * _.flip(_.list)(1, 2, 3) // => [3, 2, 1]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @returns {Function}\n */\n function flip (fn) {\n return function () {\n var args = slice(arguments).reverse();\n return fn.apply(this, args);\n };\n }\n\n /**\n * Builds a function that returns the argument received at the given index.
\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.
\n * The resulting function will return undefined if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * var getFirstArg = getArgAt(0);\n * var getLastArg = getArgAt(-1);\n *\n * getFirstArg(1, 2, 3) // => 1\n * getLastArg(1, 2, 3) // => 3\n *\n * getArgAt()(1, 2, 3) // => undefined\n * getArgAt(6)(1, 2, 3) // => undefined\n * getArgAt(1)() // => undefined\n *\n * @memberof module:lamb\n * @category Function\n * @param {Number} index\n * @returns {Function}\n */\n function getArgAt (index) {\n return compose(getAt(index), list);\n }\n\n /**\n * Builds a function that will invoke the given method name on any received object and return\n * the result. If no method with such name is found the function will return undefined.\n * Along with the method name it's possible to supply some arguments that will be bound to the method call.
\n * Further arguments can also be passed when the function is actually called, and they will be concatenated\n * to the bound ones.
\n * If different objects share a method name it's possible to build polymorphic functions as you can see in\n * the example below.
\n * {@link module:lamb.condition|Condition} can be used to wrap invoker to avoid this behaviour\n * by adding a predicate, while {@link module:lamb.adapter|adapter} can build more complex polymorphic functions\n * without the need of homonymy.
\n * Returning undefined or checking for such value is meant to favor composition and interoperability\n * between the aforementioned functions: for a more standard behaviour see also {@link module:lamb.generic|generic}.\n * See also {@link module:lamb.invokerOn|invokerOn}.\n * @example Basic polymorphism with invoker\n * var polySlice = _.invoker(\"slice\");\n *\n * polySlice([1, 2, 3, 4, 5], 1, 3) // => [2, 3]\n * polySlice(\"Hello world\", 1, 3) // => \"el\"\n *\n * @example With bound arguments\n * var substrFrom2 = _.invoker(\"substr\", 2);\n * substrFrom2(\"Hello world\") // => \"llo world\"\n * substrFrom2(\"Hello world\", 5) // => \"llo w\"\n *\n * @memberof module:lamb\n * @category Function\n * @param {String} methodName\n * @param {...*} [boundArg]\n * @returns {Function}\n */\n function invoker (methodName) {\n var boundArgs = slice(arguments, 1);\n return partial(_invoker, boundArgs, methodName);\n }\n\n /**\n * Accepts an object and builds a function expecting a method name, and optionally arguments, to call on such object.\n * Like {@link module:lamb.invoker|invoker}, if no method with the given name is found the function will return undefined.\n * @example\n * var isEven = function (n) { return n % 2 === 0; };\n * var arr = [1, 2, 3, 4, 5];\n * var invokerOnArr = _.invokerOn(arr);\n *\n * invokerOnArr(\"filter\", isEven) // => [2, 4]\n * invokerOnArr(\"slice\", 1, 3) // => [2, 3]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.invoker|invoker}\n * @param {Object} target\n * @returns {Function}\n */\n function invokerOn (target) {\n return partial(_invoker, [], _, target);\n }\n\n /**\n * Builds a function that allows to map over the received arguments before applying them to the original one.\n * @example\n * var sumArray = _.reduceWith(_.add);\n * var sum = _.compose(sumArray, _.list);\n *\n * sum(1, 2, 3, 4, 5) // => 15\n *\n * var square = _.partial(Math.pow, _, 2);\n * var sumSquares = _.mapArgs(sum, square);\n *\n * sumSquares(1, 2, 3, 4, 5) // => 55\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {ListIteratorCallback} mapper\n * @returns {Function}\n */\n function mapArgs (fn, mapper) {\n return compose(partial(apply, fn), mapWith(mapper), list);\n }\n\n /**\n * Creates a pipeline of functions, where each function consumes the result of the previous one.
\n * See also {@link module:lamb.compose|compose}.\n * @example\n * var square = _.partial(Math.pow, _, 2);\n * var getMaxAndSquare = _.pipe(Math.max, square);\n *\n * getMaxAndSquare(3, 5) // => 25\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @param {...Function} fn\n * @returns {Function}\n */\n var pipe = flip(compose);\n\n /**\n * Builds a function that allows to \"tap\" into the arguments of the original one.\n * This allows to extract simple values from complex ones, transform arguments or simply intercept them.\n * If a \"tapper\" isn't found the argument is passed as it is.\n * @example\n * var someObject = {count: 5};\n * var someArrayData = [2, 3, 123, 5, 6, 7, 54, 65, 76, 0];\n * var getDataAmount = _.tapArgs(_.add, _.getKey(\"count\"), _.getKey(\"length\"));\n *\n * getDataAmount(someObject, someArrayData); // => 15\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {...?Function} [tapper]\n * @returns {Function}\n */\n function tapArgs (fn) {\n var tappers = slice(arguments, 1);\n\n return function () {\n var len = arguments.length;\n var tappersLen = tappers.length;\n var args = [];\n\n for (var i = 0; i < len; i++) {\n args.push(i < tappersLen ? tappers[i](arguments[i]) : arguments[i]);\n }\n\n return fn.apply(this, args);\n };\n }\n\n /**\n * Returns a function that will invoke the passed function at most once in the given timespan.
\n * The first call in this case happens as soon as the function is invoked; see also {@link module:lamb.debounce|debounce}\n * for a different behaviour where the first call is delayed.\n * @example\n * var log = _.throttle(console.log.bind(console), 5000);\n *\n * log(\"Hi\"); // console logs \"Hi\"\n * log(\"Hi again\"); // nothing happens\n * // after five seconds\n * log(\"Hello world\"); // console logs \"Hello world\"\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @param {Number} timespan - Expressed in milliseconds.\n * @returns {Function}\n */\n function throttle (fn, timespan) {\n var result;\n var lastCall = 0;\n\n return function () {\n var now = Date.now();\n\n if (now - lastCall >= timespan) {\n lastCall = now;\n result = fn.apply(this, arguments);\n }\n\n return result;\n };\n }\n\n /**\n * Builds a function that passes only one argument to the given function.
\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.
\n * See also {@link module:lamb.binary|binary}.\n * @example\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * weights.map(_.unary(parseInt)) // => [2, 10, 1, 7]\n *\n * @memberof module:lamb\n * @category Function\n * @param {Function} fn\n * @returns {Function}\n */\n function unary (fn) {\n return function (a) {\n return fn.call(this, a);\n };\n }\n\n /**\n * Wraps the function fn inside a wrapper function.
\n * This allows to conditionally execute fn, to tamper with its arguments or return value\n * and to run code before and after its execution.
\n * Being this nothing more than a \"{@link module:lamb.flip|flipped}\" [partial application]{@link module:lamb.partial},\n * you can also easily build new functions from existent ones.\n * @example\n * var arrayMax = _.wrap(Math.max, _.apply);\n *\n * arrayMax([4, 5, 2, 6, 1]) // => 6\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @param {Function} fn\n * @param {Function} wrapper\n * @returns {Function}\n */\n var wrap = binary(flip(partial));\n\n lamb.apply = apply;\n lamb.applyArgs = applyArgs;\n lamb.aritize = aritize;\n lamb.binary = binary;\n lamb.collect = collect;\n lamb.curry = curry;\n lamb.curryRight = curryRight;\n lamb.curryable = curryable;\n lamb.curryableRight = curryableRight;\n lamb.debounce = debounce;\n lamb.flip = flip;\n lamb.getArgAt = getArgAt;\n lamb.invoker = invoker;\n lamb.invokerOn = invokerOn;\n lamb.mapArgs = mapArgs;\n lamb.pipe = pipe;\n lamb.tapArgs = tapArgs;\n lamb.throttle = throttle;\n lamb.unary = unary;\n lamb.wrap = wrap;\n\n\n /**\n * Builds a checker function meant to be used with {@link module:lamb.validate|validate}.
\n * Note that the function accepts multiple keyPaths as a means to compare their values. In\n * other words all the received keyPaths will be passed as arguments to the predicate\n * to run the test.
\n * If you want to run the same single property check with multiple properties, you should build\n * multiple checkers and combine them with {@link module:lamb.validate|validate}.\n * @example\n * var user = {\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * username: \"jdoe\",\n * password: \"abc123\",\n * passwordConfirm: \"abc123\"\n * }\n * };\n * var pwdMatch = _.checker(\n * _.is,\n * \"Passwords don't match\",\n * [\"login.password\", \"login.passwordConfirm\"]\n * );\n *\n * pwdMatch(user) // => []\n *\n * var newUser = _.setPathIn(user, \"login.passwordConfirm\", \"avc123\");\n *\n * pwdMatch(newUser) // => [\"Passwords don't match\", [\"login.password\", \"login.passwordConfirm\"]]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validate|validate}, {@link module:lamb.validateWith|validateWith}\n * @param {Function} predicate - The predicate to test the object properties\n * @param {String} message - The error message\n * @param {String[]} keyPaths - The array of property names, or {@link module:lamb.getPathIn|paths}, to test.\n * @param {String} [pathSeparator=\".\"]\n * @returns {Array} An error in the form [\"message\", [\"propertyA\", \"propertyB\"]] or an empty array.\n */\n function checker (predicate, message, keyPaths, pathSeparator) {\n return function (obj) {\n var getValues = partial(getPathIn, obj, _, pathSeparator);\n return predicate.apply(obj, map(keyPaths, getValues)) ? [] : [message, keyPaths];\n };\n }\n\n /**\n * Creates an array with all the enumerable properties of the given object.\n * @example Showing the difference with {@link module:lamb.keys|keys}\n * var baseFoo = Object.create({a: 1}, {b: {value: 2}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3},\n * d: {value: 4, enumerable: true}\n * });\n *\n * _.keys(foo) // => [\"d\"]\n * _.enumerables(foo) // => [\"d\", \"a\"]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.keys|keys}\n * @param {Object} obj\n * @returns {String[]}\n */\n var enumerables = _unsafeKeyListFrom(_safeEnumerables);\n\n /**\n * Builds an object from a list of key / value pairs like the one\n * returned by [pairs]{@link module:lamb.pairs} or {@link module:lamb.ownPairs|ownPairs}.
\n * In case of duplicate keys the last key / value pair is used.\n * @example\n * _.fromPairs([[\"a\", 1], [\"b\", 2], [\"c\", 3]]) // => {\"a\": 1, \"b\": 2, \"c\": 3}\n * _.fromPairs([[\"a\", 1], [\"b\", 2], [\"a\", 3]]) // => {\"a\": 3, \"b\": 2}\n * _.fromPairs([[1], [void 0, 2], [null, 3]]) // => {\"1\": undefined, \"undefined\": 2, \"null\": 3}\n *\n * @memberof module:lamb\n * @category Object\n * @param {Array>} pairsList\n * @returns {Object}\n */\n function fromPairs (pairsList) {\n var result = {};\n\n forEach(pairsList, function (pair) {\n result[pair[0]] = pair[1];\n });\n\n return result;\n }\n\n /**\n * Verifies the existence of a property in an object.\n * @example\n * var user1 = {name: \"john\"};\n *\n * _.has(user1, \"name\") // => true\n * _.has(user1, \"surname\") // => false\n * _.has(user1, \"toString\") // => true\n *\n * var user2 = Object.create(null);\n *\n * // not inherited through the prototype chain\n * _.has(user2, \"toString\") // => false\n *\n * @memberof module:lamb\n * @category Object\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n function has (obj, key) {\n if (typeof obj !== \"object\" && !isUndefined(obj)) {\n obj = Object(obj);\n }\n\n return key in obj;\n }\n\n /**\n * Curried version of {@link module:lamb.has|has}.
\n * Returns a function expecting the object to check against the given key.\n * @example\n * var user1 = {name: \"john\"};\n * var user2 = {};\n * var hasName = _.hasKey(\"name\");\n *\n * hasName(user1) // => true\n * hasName(user2) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @param {String} key\n * @returns {Function}\n */\n function hasKey (key) {\n return function (obj) {\n return has(obj, key);\n };\n }\n\n /**\n * Builds a function expecting an object to check against the given key / value pair.\n * @example\n * var hasTheCorrectAnswer = _.hasKeyValue(\"answer\", 42);\n *\n * hasTheCorrectAnswer({answer: 2}) // false\n * hasTheCorrectAnswer({answer: 42}) // true\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {String} key\n * @param {*} value\n * @returns {Function}\n */\n var hasKeyValue = function (key, value) {\n return compose(partial(is, value), getKey(key));\n };\n\n /**\n * Verifies if an object has the specified property and that the property isn't inherited through\n * the prototype chain.
\n * @example Comparison with has.\n * var user = {name: \"john\"};\n *\n * _.has(user, \"name\") // => true\n * _.has(user, \"surname\") // => false\n * _.has(user, \"toString\") // => true\n *\n * _.hasOwn(user, \"name\") // => true\n * _.hasOwn(user, \"surname\") // => false\n * _.hasOwn(user, \"toString\") // => false\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @param {String} key\n * @returns {Boolean}\n */\n var hasOwn = generic(_objectProto.hasOwnProperty);\n\n /**\n * Curried version of {@link module:lamb.hasOwn|hasOwn}.
\n * Returns a function expecting the object to check against the given key.\n * @example\n * var user = {name: \"john\"};\n * var hasOwnName = _.hasOwnKey(\"name\");\n * var hasOwnToString = _.hasOwnToString(\"toString\");\n *\n * hasOwnName(user) // => true\n * hasOwnToString(user) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @param {String} key\n * @returns {Function}\n */\n function hasOwnKey (key) {\n return function (obj) {\n return hasOwn(obj, key);\n };\n }\n\n /**\n * Makes an object immutable by recursively calling [Object.freeze]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze}\n * on its members.
\n * Any attempt to extend or modify the object can throw a TypeError or fail silently,\n * depending on the environment and the [strict mode]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode} directive.\n * @example\n * var user = _.immutable({\n * name: \"John\",\n * surname: \"Doe\",\n * login: {\n * username: \"jdoe\",\n * password: \"abc123\"\n * },\n * luckyNumbers: [13, 17]\n * });\n *\n * // All of these statements will fail and possibly\n * // throw a TypeError (see the function description)\n * user.name = \"Joe\";\n * delete user.name;\n * user.newProperty = [];\n * user.login.password = \"foo\";\n * user.luckyNumbers.push(-13);\n *\n * @memberof module:lamb\n * @category Object\n * @param {Object} obj\n * @returns {Object}\n */\n function immutable (obj) {\n return _immutable(obj, []);\n }\n\n /**\n * Retrieves the list of the own enumerable properties of an object.
\n * Although [Object.keys]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys}\n * is already present in ECMAScript 5, its behaviour changed in the subsequent specifications\n * of the standard as you can read in the link above.
\n * This function shims the ECMAScript 6 version, by forcing a conversion to\n * object for any value but null and undefined.\n * @example Showing the difference with {@link module:lamb.enumerables|enumerables}\n * var baseFoo = Object.create({a: 1}, {b: {value: 2}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3},\n * d: {value: 4, enumerable: true}\n * });\n *\n * _.enumerables(foo) // => [\"d\", \"a\"]\n * _.keys(foo) // => [\"d\"]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.enumerables|enumerables}\n * @param {Object} obj\n * @returns {String[]}\n */\n var keys = _unsafeKeyListFrom(_safeKeys);\n\n /**\n * Builds an object from the two given lists, using the first one as keys and the last one as values.
\n * If the list of keys is longer than the values one, the keys will be created with undefined values.
\n * If more values than keys are supplied, the extra values will be ignored.
\n * See also {@link module:lamb.tear|tear} and {@link module:lamb.tearOwn|tearOwn} for the reverse operation.\n * @example\n * _.make([\"a\", \"b\", \"c\"], [1, 2, 3]) // => {a: 1, b: 2, c: 3}\n * _.make([\"a\", \"b\", \"c\"], [1, 2]) // => {a: 1, b: 2, c: undefined}\n * _.make([\"a\", \"b\"], [1, 2, 3]) // => {a: 1, b: 2}\n * _.make([null, void 0, 2], [1, 2, 3]) // => {\"null\": 1, \"undefined\": 2, \"2\": 3}\n *\n * @memberof module:lamb\n * @category Object\n * @param {String[]} keys\n * @param {ArrayLike} values\n * @returns {Object}\n */\n function make (keys, values) {\n var result = {};\n var valuesLen = values.length;\n\n for (var i = 0, len = keys.length; i < len; i++) {\n result[keys[i]] = i < valuesLen ? values[i] : void 0;\n }\n\n return result;\n }\n\n /**\n * Merges the enumerable properties of the provided sources into a new object.
\n * In case of key homonymy each source has precedence over the previous one.
\n * See also {@link module:lamb.mergeOwn|mergeOwn} for merging only own properties of\n * the given sources.\n * @example\n * _.merge({a: 1}, {b: 3, c: 4}, {b: 5}) // => {a: 1, b: 5, c: 4}\n *\n * @example Arrays and array-like objects will be transformed to objects with numbers as keys:\n * _.merge([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.merge(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other value will be treated as an empty object:\n * _.merge({a: 2}, null, NaN) // => {a: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {...Object} source\n * @returns {Object}\n */\n var merge = partial(_merge, _safeEnumerables);\n\n /**\n * Same as {@link module:lamb.merge|merge}, but only the own properties of the sources are taken into account.\n * @example showing the difference with merge:\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * var bar = {d: 4};\n *\n * _.merge(foo, bar) // => {a: 1, b: 2, c: 3, d: 4}\n * _.mergeOwn(foo, bar) // => {c: 3, d: 4}\n *\n * @example Arrays or array-like objects will be transformed to objects with numbers as keys:\n * _.mergeOwn([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.mergeOwn(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other value will be treated as an empty object:\n * _.mergeOwn({a: 2}, null, NaN) // => {a: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {...Object} source\n * @returns {Object}\n */\n var mergeOwn = partial(_merge, _safeKeys);\n\n /**\n * Same as {@link module:lamb.pairs|pairs}, but only the own enumerable properties of the object are\n * taken into account.
\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example showing the difference with pairs\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * _.pairs(foo) // => [[\"c\", 3], [\"b\", 2], [\"a\", 1]]\n * _.ownPairs(foo) // => [[\"c\", 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array>}\n */\n var ownPairs = _pairsFrom(keys);\n\n /**\n * Same as {@link module:lamb.values|values}, but only the own enumerable properties of the object are\n * taken into account.
\n * @example showing the difference with values\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * _.values(foo) // => [3, 2, 1]\n * _.ownValues(foo) // => [3]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array}\n */\n var ownValues = _valuesFrom(keys);\n\n /**\n * Converts an object into an array of key / value pairs of its enumerable properties.
\n * See also {@link module:lamb.ownPairs|ownPairs} for picking only the own enumerable\n * properties and {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example\n * _.pairs({a: 1, b: 2, c: 3}) // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array>}\n */\n var pairs = _pairsFrom(enumerables);\n\n /**\n * Returns an object containing only the specified properties of the given object.
\n * Non existent properties will be ignored.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.pick(user, [\"name\", \"age\"]) // => {\"name\": \"john\", \"age\": 30};\n * _.pick(user, [\"name\", \"email\"]) // => {\"name\": \"john\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pickIf|pickIf}, {@link module:lamb.pickKeys|pickKeys}\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipIf|skipIf}\n * @param {Object} source\n * @param {String[]} whitelist\n * @returns {Object}\n */\n function pick (source, whitelist) {\n var result = {};\n\n forEach(whitelist, function (key) {\n if (has(source, key)) {\n result[key] = source[key];\n }\n });\n\n return result;\n }\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked against the given predicate.
\n * The properties satisfying the predicate will be included in the resulting object.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n * var pickIfIsString = _.pickIf(_.isType(\"String\"));\n *\n * pickIfIsString(user) // => {name: \"john\", surname: \"doe\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipKeys|skipKeys}, {@link module:lamb.skipIf|skipIf}\n * @param {ObjectIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n function pickIf (predicate, predicateContext) {\n if (arguments.length === 2) {\n predicate = predicate.bind(predicateContext);\n }\n\n return function (source) {\n var result = {};\n\n forEach(enumerables(source), function (key) {\n if (predicate(source[key], key, source)) {\n result[key] = source[key];\n }\n });\n\n return result;\n };\n }\n\n /**\n * A curried version of {@link module:lamb.pick|pick}, expecting a whitelist of keys to build\n * a function waiting for the object to act upon.\n * @example\n * var user = {id: 1, name: \"Jane\", surname: \"Doe\", active: false};\n * var getUserInfo = _.pickKeys([\"id\", \"active\"]);\n *\n * getUserInfo(user) // => {id: 1, active: false}\n *\n * @example A useful composition with mapWith:\n * var users = [\n * {id: 1, name: \"Jane\", surname: \"Doe\", active: false},\n * {id: 2, name: \"John\", surname: \"Doe\", active: true},\n * {id: 3, name: \"Mario\", surname: \"Rossi\", active: true},\n * {id: 4, name: \"Paolo\", surname: \"Bianchi\", active: false}\n * ];\n * var select = _.compose(_.mapWith, _.pickKeys);\n * var selectUserInfo = select([\"id\", \"active\"]);\n *\n * selectUserInfo(users) // =>\n * // [\n * // {id: 1, active: false},\n * // {id: 2, active: true},\n * // {id: 3, active: true},\n * // {id: 4, active: false}\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickIf|pickIf}\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipKeys|skipKeys}, {@link module:lamb.skipIf|skipIf}\n * @param {String[]} whitelist\n * @returns {Function}\n */\n var pickKeys = _curry(pick, 2, true);\n\n /**\n * Creates a copy of the given object with its enumerable keys renamed as\n * indicated in the provided lookup table.\n * @example\n * var person = {\"firstName\": \"John\", \"lastName\": \"Doe\"};\n * var keysMap = {\"firstName\": \"name\", \"lastName\": \"surname\"};\n *\n * _.rename(person, keysMap) // => {\"name\": \"John\", \"surname\": \"Doe\"}\n *\n * @example It's safe using it to swap keys:\n * var keysMap = {\"firstName\": \"lastName\", \"lastName\": \"firstName\"};\n *\n * _.rename(person, keysMap) // => {\"lastName\": \"John\", \"firstName\": \"Doe\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.renameKeys|renameKeys}, {@link module:lamb.renameWith|renameWith}\n * @param {Object} source\n * @param {Object} keysMap\n * @returns {Object}\n */\n function rename (source, keysMap) {\n keysMap = Object(keysMap);\n var result = {};\n var oldKeys = enumerables(source);\n\n for (var prop in keysMap) {\n if (~oldKeys.indexOf(prop)) {\n result[keysMap[prop]] = source[prop];\n }\n }\n\n for (var i = 0, len = oldKeys.length, key; i < len; i++) {\n key = oldKeys[i];\n\n if (!(key in keysMap || key in result)) {\n result[key] = source[key];\n }\n }\n\n return result;\n }\n\n /**\n * A curried version of {@link module:lamb.rename|rename} expecting a\n * keysMap to build a function waiting for the object to act upon.\n * @example\n * var persons = [\n * {\"firstName\": \"John\", \"lastName\": \"Doe\"},\n * {\"first_name\": \"Mario\", \"last_name\": \"Rossi\"},\n * ];\n * var normalizeKeys = _.renameKeys({\n * \"firstName\": \"name\",\n * \"first_name\": \"name\",\n * \"lastName\": \"surname\",\n * \"last_name\": \"surname\"\n * });\n *\n * persons.map(normalizeKeys) // => [{\"name\": \"John\", \"surname\": \"Doe\"}, {\"name\": \"Mario\", \"surname\": \"Rossi\"}]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.rename|rename}, {@link module:lamb.renameWith|renameWith}\n * @param {Object} keysMap\n * @returns {Function}\n */\n var renameKeys = _curry(rename, 2, true);\n\n /**\n * Uses the provided function as a keysMap generator and returns\n * a function expecting the object whose keys we want to {@link module:lamb.rename|rename}.\n * @example\n * var person = {\"NAME\": \"John\", \"SURNAME\": \"Doe\"};\n * var makeLowerKeysMap = function (source) {\n * var sourceKeys = _.keys(source);\n * return _.make(sourceKeys, sourceKeys.map(_.invoker(\"toLowerCase\")));\n * };\n * var lowerKeysFor = _.renameWith(makeLowerKeysMap);\n *\n * lowerKeysFor(person) // => {\"name\": \"John\", \"surname\": \"doe\"};\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.rename|rename}, {@link module:lamb.renameKeys|renameKeys}\n * @param {Function} fn\n * @returns {Function}\n */\n function renameWith (fn) {\n return function (source) {\n return rename(source, fn(source));\n };\n }\n\n /**\n * Returns a copy of the source object without the specified properties.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.skip(user, [\"name\", \"age\"]) // => {surname: \"doe\"};\n * _.skip(user, [\"name\", \"email\"]) // => {surname: \"doe\", age: 30};\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.skipKeys|skipKeys}, {@link module:lamb.skipIf|skipIf}\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}, {@link module:lamb.pickIf|pickIf}\n * @param {Object} source\n * @param {String[]} blacklist\n * @returns {Object}\n */\n function skip (source, blacklist) {\n var result = {};\n\n forEach(enumerables(source), function (key) {\n if (!isIn(blacklist, key)) {\n result[key] = source[key];\n }\n });\n\n return result;\n }\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked against the given predicate.
\n * The properties satisfying the predicate will be omitted in the resulting object.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n * var skipIfIstring = _.skipIf(_.isType(\"String\"));\n *\n * skipIfIstring(user) // => {age: 30}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipKeys|skipKeys}\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}, {@link module:lamb.pickIf|pickIf}\n * @param {ObjectIteratorCallback} predicate\n * @param {Object} [predicateContext]\n * @returns {Function}\n */\n var skipIf = tapArgs(pickIf, not);\n\n /**\n * A curried version of {@link module:lamb.skip|skip}, expecting a blacklist of keys to build\n * a function waiting for the object to act upon.\n * @example\n * var user = {id: 1, name: \"Jane\", surname: \"Doe\", active: false};\n * var getUserInfo = _.skipKeys([\"name\", \"surname\"]);\n *\n * getUserInfo(user) // => {id: 1, active: false}\n *\n * @example A useful composition with mapWith:\n * var users = [\n * {id: 1, name: \"Jane\", surname: \"Doe\", active: false},\n * {id: 2, name: \"John\", surname: \"Doe\", active: true},\n * {id: 3, name: \"Mario\", surname: \"Rossi\", active: true},\n * {id: 4, name: \"Paolo\", surname: \"Bianchi\", active: false}\n * ];\n * var discard = _.compose(_.mapWith, _.skipKeys);\n * var discardNames = discard([\"name\", \"surname\"]);\n *\n * discardNames(users) // =>\n * // [\n * // {id: 1, active: false},\n * // {id: 2, active: true},\n * // {id: 3, active: true},\n * // {id: 4, active: false}\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipIf|skipIf}\n * @see {@link module:lamb.pick|pick}, {@link module:lamb.pickKeys|pickKeys}, {@link module:lamb.pickIf|pickIf}\n * @param {String[]} blacklist\n * @returns {Function}\n */\n var skipKeys = _curry(skip, 2, true);\n\n /**\n * Tears an object apart by transforming it in an array of two lists: one containing its enumerable keys,\n * the other containing the corresponding values.
\n * Although this \"tearing apart\" may sound as a rather violent process, the source object will be unharmed.
\n * See also {@link module:lamb.tearOwn|tearOwn} for picking only the own enumerable properties and\n * {@link module:lamb.make|make} for the reverse operation.\n * @example\n * _.tear({a: 1, b: 2, c: 3}) // => [[\"a\", \"b\", \"c\"], [1, 2, 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array, Array<*>>}\n */\n var tear = _tearFrom(enumerables);\n\n /**\n * Same as {@link module:lamb.tear|tear}, but only the own properties of the object are taken into account.
\n * See also {@link module:lamb.make|make} for the reverse operation.\n * @example showing the difference with tear\n * var baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * var foo = Object.create(baseFoo, {\n * c: {value: 3, enumerable: true}\n * });\n *\n * _.tear(foo) // => [[\"c\", \"b\", \"a\"], [3, 2, 1]]\n * _.tearOwn(foo) // => [[\"c\"], [3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array, Array<*>>}\n */\n var tearOwn = _tearFrom(keys);\n\n /**\n * Validates an object with the given list of {@link module:lamb.checker|checker} functions.\n * @example\n * var hasContent = function (s) { return s.trim().length > 0; };\n * var isAdult = function (age) { return age >= 18; };\n * var userCheckers = [\n * _.checker(hasContent, \"Name is required\", [\"name\"]),\n * _.checker(hasContent, \"Surname is required\", [\"surname\"]),\n * _.checker(isAdult, \"Must be at least 18 years old\", [\"age\"])\n * ];\n *\n * var user1 = {name: \"john\", surname: \"doe\", age: 30};\n * var user2 = {name: \"jane\", surname: \"\", age: 15};\n *\n * _.validate(user1, userCheckers) // => []\n * _.validate(user2, userCheckers) // => [[\"Surname is required\", [\"surname\"]], [\"Must be at least 18 years old\", [\"age\"]]]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validateWith|validateWith}\n * @see {@link module:lamb.checker|checker}\n * @param {Object} obj\n * @param {Function[]} checkers\n * @returns {Array>} An array of errors in the form returned by {@link module:lamb.checker|checker}, or an empty array.\n */\n function validate (obj, checkers) {\n return reduce(checkers, function (errors, checker) {\n var result = checker(obj);\n result.length && errors.push(result);\n return errors;\n }, []);\n }\n\n /**\n * A curried version of {@link module:lamb.validate|validate} accepting a list of {@link module:lamb.checker|checkers} and\n * returning a function expecting the object to validate.\n * @example\n * var hasContent = function (s) { return s.trim().length > 0; };\n * var isAdult = function (age) { return age >= 18; };\n * var userCheckers = [\n * _.checker(hasContent, \"Name is required\", [\"name\"]),\n * _.checker(hasContent, \"Surname is required\", [\"surname\"]),\n * _.checker(isAdult, \"Must be at least 18 years old\", [\"age\"])\n * ];\n * var validateUser = _.validateWith(userCheckers);\n *\n * var user1 = {name: \"john\", surname: \"doe\", age: 30};\n * var user2 = {name: \"jane\", surname: \"\", age: 15};\n *\n * validateUser(user1) // => []\n * validateUser(user2) // => [[\"Surname is required\", [\"surname\"]], [\"Must be at least 18 years old\", [\"age\"]]]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validate|validate}\n * @see {@link module:lamb.checker|checker}\n * @function\n * @param {Function[]} checkers\n * @returns {Function}\n */\n var validateWith = _curry(validate, 2, true);\n\n /**\n * Generates an array with the values of the enumerable properties of the given object.
\n * See also {@link module:lamb.ownValues|ownValues} for picking only the own properties of the object.\n * @example\n * var user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.values(user) // => [\"john\", \"doe\", 30]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @param {Object} obj\n * @returns {Array}\n */\n var values = _valuesFrom(enumerables);\n\n lamb.checker = checker;\n lamb.enumerables = enumerables;\n lamb.fromPairs = fromPairs;\n lamb.has = has;\n lamb.hasKey = hasKey;\n lamb.hasKeyValue = hasKeyValue;\n lamb.hasOwn = hasOwn;\n lamb.hasOwnKey = hasOwnKey;\n lamb.immutable = immutable;\n lamb.keys = keys;\n lamb.make = make;\n lamb.merge = merge;\n lamb.mergeOwn = mergeOwn;\n lamb.ownPairs = ownPairs;\n lamb.ownValues = ownValues;\n lamb.pairs = pairs;\n lamb.pick = pick;\n lamb.pickIf = pickIf;\n lamb.pickKeys = pickKeys;\n lamb.rename = rename;\n lamb.renameKeys = renameKeys;\n lamb.renameWith = renameWith;\n lamb.skip = skip;\n lamb.skipIf = skipIf;\n lamb.skipKeys = skipKeys;\n lamb.tear = tear;\n lamb.tearOwn = tearOwn;\n lamb.validate = validate;\n lamb.validateWith = validateWith;\n lamb.values = values;\n\n\n /**\n * Pads a string to the desired length with the given char starting from the beginning of the string.\n * @example\n * _.padLeft(\"foo\", \"-\", 0) // => \"foo\"\n * _.padLeft(\"foo\", \"-\", -1) // => \"foo\"\n * _.padLeft(\"foo\", \"-\", 5) // => \"--foo\"\n * _.padLeft(\"foo\", \"-\", 3) // => \"foo\"\n * _.padLeft(\"foo\", \"ab\", 7) // => \"aaaafoo\"\n * _.padLeft(\"foo\", \"\", 5) // => \" foo\"\n * _.padLeft(\"\", \"-\", 5) // => \"-----\"\n *\n * @memberof module:lamb\n * @category String\n * @param {String} source\n * @param {String} [char=\" \"] - The padding char. If a string is passed only the first char is used.\n * @param {Number} len\n * @returns {String}\n */\n function padLeft (source, char, len) {\n return _getPadding(source, char, len) + source;\n }\n\n /**\n * Pads a string to the desired length with the given char starting from the end of the string.\n * @example\n * _.padRight(\"foo\", \"-\", 0) // => \"foo\"\n * _.padRight(\"foo\", \"-\", -1) // => \"foo\"\n * _.padRight(\"foo\", \"-\", 5) // => \"foo--\"\n * _.padRight(\"foo\", \"-\", 3) // => \"foo\"\n * _.padRight(\"foo\", \"ab\", 7) // => \"fooaaaa\"\n * _.padRight(\"foo\", \"\", 5) // => \"foo \"\n * _.padRight(\"\", \"-\", 5) // => \"-----\"\n *\n * @memberof module:lamb\n * @category String\n * @param {String} source\n * @param {String} [char=\" \"] - The padding char. If a string is passed only the first char is used.\n * @param {Number} len\n * @returns {String}\n */\n function padRight (source, char, len) {\n return source + _getPadding(source, char, len);\n }\n\n /**\n * Builds a new string by repeating the source string the desired amount of times.
\n * Note that unlike the current ES6 proposal for [String.prototype.repeat]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat},\n * this function doesn't throw a RangeError if count is negative, but returns an empty string instead.\n * @example\n * _.repeat(\"Hello\", -1) // => \"\"\n * _.repeat(\"Hello\", 1) // => \"Hello\"\n * _.repeat(\"Hello\", 3) // => \"HelloHelloHello\"\n *\n * @memberof module:lamb\n * @category String\n * @param {String} source\n * @param {Number} count\n * @returns {String}\n */\n function repeat (source, count) {\n var result = \"\";\n\n for (var i = 0; i < count; i++) {\n result += source;\n }\n\n return result;\n }\n\n /**\n * Builds a predicate expecting a string to test against the given regular expression pattern.\n * @example\n * var hasNumbersOnly = _.testWith(/^\\d+$/);\n *\n * hasNumbersOnly(\"123\") // => true\n * hasNumbersOnly(\"123 Kg\") // => false\n *\n * @memberof module:lamb\n * @category String\n * @param {RegExp} pattern\n * @returns {Function}\n */\n function testWith (pattern) {\n return _reProto.test.bind(pattern);\n }\n\n lamb.padLeft = padLeft;\n lamb.padRight = padRight;\n lamb.repeat = repeat;\n lamb.testWith = testWith;\n\n /* istanbul ignore next */\n if (typeof exports === \"object\") {\n module.exports = lamb;\n } else if (typeof define === \"function\" && define.amd) {\n define(function() { return lamb; });\n } else {\n host.lamb = lamb;\n }\n}(this);\n\n/**\n * @callback AccumulatorCallback\n * @global\n * @param {*} previousValue The value returned it the last execution of the accumulator or, in the first iteration, the {@link module:lamb.reduce|initialValue} if supplied.\n * @param {*} currentValue The value being processed in the current iteration.\n * @param {Number} idx - The index of the element being processed.\n * @param {ArrayLike} arrayLike - The list being traversed.\n */\n\n/**\n * The built-in arguments object.\n * @typedef {arguments} arguments\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments|arguments} in Mozilla documentation.\n */\n\n/**\n * The built-in Array object.\n * @typedef {Array} Array\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array|Array} in Mozilla documentation.\n */\n\n/**\n * Any array-like object.\n * @typedef {Array|String|arguments|?} ArrayLike\n * @global\n */\n\n/**\n * The built-in Boolean object.\n * @typedef {Boolean} Boolean\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean|Boolean} in Mozilla documentation.\n */\n\n/**\n * The built-in Date object.\n * @typedef {Date} Date\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date|Date} in Mozilla documentation.\n */\n\n/**\n * The built-in Function object.\n * @typedef {Function} function\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function|Function} and\n * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions|Functions} in Mozilla documentation.\n */\n\n/**\n * @callback ListIteratorCallback\n * @global\n * @param {*} element - The element being evaluated.\n * @param {Number} idx - The index of the element within the list.\n * @param {ArrayLike} arrayLike - The list being traversed.\n */\n\n/**\n * The built-in Number object.\n * @typedef {Number} Number\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number|Number} in Mozilla documentation.\n */\n\n/**\n * The built-in Object object.\n * @typedef {Object} Object\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object|Object} in Mozilla documentation.\n */\n\n/**\n * @callback ObjectIteratorCallback\n * @global\n * @param {*} value - The value of the current property.\n * @param {String} key - The property name.\n * @param {Object} source - The object being traversed.\n */\n\n/**\n * The built-in RegExp object.\n * @typedef {RegExp} RegExp\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp|RegExp} in Mozilla documentation.\n */\n\n/**\n * Represent a sorting criteria used by {@link module:lamb.sortedInsert|sortedInsert}, {@link module:lamb.sort|sort} and {@link module:lamb.sortWith|sortWith},\n * and it's usually built using {@link module:lamb.sorter|sorter} and {@link module:lamb.sorterDesc|sorterDesc}.\n * @typedef {Sorter} Sorter\n * @global\n * @property {Boolean} isDescending\n * @property {Function} compare\n */\n\n/**\n * The built-in String object.\n * @typedef {String} String\n * @global\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String|String} in Mozilla documentation.\n */\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 65b275c..32805ed 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -62,7 +62,7 @@ gulp.task("minify", ["concat"], function () { return gulp.src("./dist/lamb.js") .pipe(sourcemaps.init()) .pipe(uglify({ - preserveComments: "some" + preserveComments: "license" })) .pipe(rename({extname: ".min.js"})) .pipe(sourcemaps.write("./")) diff --git a/package.json b/package.json index bd4733e..77b292f 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,9 @@ "coveralls": "gulp coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" }, "tonicExample": "var _ = require('lamb');", - "version": "0.35.0", + "version": "0.36.0-alpha.3", "devDependencies": { - "coveralls": "^2.11.11", + "coveralls": "^2.11.12", "gulp": "^3.9.1", "gulp-concat": "^2.6.0", "gulp-footer": "^1.0.5", @@ -43,9 +43,9 @@ "gulp-jasmine": "^2.4.0", "gulp-rename": "^1.2.2", "gulp-sourcemaps": "^1.6.0", - "gulp-uglify": "^1.5.4", + "gulp-uglify": "^2.0.0", "plato": "^1.6.0", - "sinon": "^1.17.4" + "sinon": "^1.17.5" }, "dependencies": {} }