{"version":3,"file":"lamb.min.mjs","names":["__","always","value","areSVZ","a","b","binary","fn","call","this","clamp","n","min","max","NaN","partial","args","Array","isArray","apply","arguments","boundArg","lastIdx","newArgs","argsLen","length","i","len","_makePartial3","shouldAritize","clampWithin","identity","compose","MAX_ARRAY_LENGTH","MAX_SAFE_INTEGER","_toArrayLength","forEach","arrayLike","iteratee","generic","Function","bind","isNull","isUndefined","isNil","_curry2","isRightCurry","isSVZ","map","result","mapWith","partialRight","boundArgs","j","_makeReducer","step","accumulator","initialValue","nCalls","idx","TypeError","reduce","reduceWith","_toInteger","Math","floor","abs","slice","start","end","begin","upTo","resultLen","sliceAt","objectProtoToString","Object","prototype","toString","type","appendTo","concat","append","isIn","contains","_groupWith","makeValue","element","key","count","countBy","nativeSlice","_isArrayLike","target","_LookupHelper","hasNativeSet","Set","sourceElements","sourceElementsSet","add","push","has","_makeTypeErrorFor","desiredType","toLowerCase","filter","predicate","uniquesBy","seen","uniques","difference","toExclude","v","dropFrom","drop","_getLastHitIndex","fromLast","increment","_takeOrDropWhile","isTake","idxFrom","idxTo","lastHitIndex","dropLastWhile","dropWhile","_makeArrayChecker","defaultResult","everyIn","every","filterWith","_findIndex","findIndex","find","findIndexWhere","findLastIndex","findLast","findLastIndexWhere","findLastWhere","findWhere","flatMap","array","el","arr","rLen","flatMapWith","_flatten","isDeep","output","vLen","_makeArrayFlattener","flatten","_toNaturalIndex","getIndex","index","getAt","group","groupBy","head","indexBy","init","insert","splice","insertAt","intersection","resultLookup","bLookup","lenA","join","separator","String","joinWith","last","_argsToArrayFrom","list","partition","partitionWith","getIn","source","getKey","pluck","pluckFrom","pullFrom","values","pull","reduceRight","reduceRightWith","reverse","ofs","rotate","amount","shift","rotateBy","_setIndex","updater","setAt","aritize","arity","setIndex","shallowFlatten","someIn","some","_compareWith","criteria","criterion","compare","isDescending","_comparer","_sorter","reader","comparer","_makeCriterion","_makeCriteria","sorters","sort","_getInsertionIndex","pivot","sortedInsert","sorter","sorterDesc","sortWith","symmetricDifference","tail","takeFrom","take","takeLastWhile","takeWhile","transpose","minLen","elementLen","pipe","functions","unionBy","union","updateAt","updateIndex","zip","zipWithIndex","application","applyTo","_asPartial","argsHolder","asPartial","collect","_currier","isAutoCurry","holderLen","newArgsLen","_curry3","c","_curry","curry","curryable","curryableRight","curryRight","debounce","timespan","timeoutID","debounced","clearTimeout","setTimeout","flip","getArgAt","_invoke","methodName","method","boundArgsLen","finalArgsLen","finalArgs","invoke","invokeOn","mapArgs","mapper","tapArgs","tappers","tappersLen","throttle","lastCall","now","Date","unary","adapter","_checkPredicates","checkAll","predicates","allOf","anyOf","areSame","casus","condition","trueFn","falseFn","gt","gte","is","isGT","isGTE","lt","isLT","lte","isLTE","not","unless","when","sum","subtract","deduct","divide","divideBy","generate","limit","isFinite_","isFinite","isInteger","isSafeInteger","mean","numbers","r","median","sortedNumbers","Number","modulo","multiply","multiplyBy","randomInt","random","_forceToNumber","range","ceil","remainder","_isOwnEnumerable","propertyIsEnumerable","_safeEnumerables","_isEnumerable","indexOf","_getPathKey","includeNonEnumerables","_getPathInfo","parts","walkNonEnumerables","isValid","_toPathParts","path","split","getPathIn","checker","message","keyPaths","pathSeparator","obj","getValues","_unsafeKeyListFrom","getKeys","enumerables","fromPairs","pairsList","pair","getPath","hasKey","hasOwn","hasOwnProperty","hasOwnKey","hasKeyValue","hasPathValue","pathInfo","_safeKeys","keys","keySatisfies","make","names","valuesLen","mapValues","mapValuesWith","_merge","merge","mergeOwn","_keyToPairIn","_pairsFrom","ownPairs","_valuesFrom","ownValues","pairs","pathExistsIn","pathExists","pathSatisfies","pickIn","whitelist","pick","pickIf","renameIn","keysMap","oldKeys","prop","rename","renameWith","_setIn","setIn","setKey","_isArrayIndex","_setPathIn","partsLen","targetKey","setPathIn","setPath","skipIn","blacklist","props","skip","skipIf","_tearFrom","tear","tearOwn","updateIn","updateKey","updatePathIn","updatePath","validate","checkers","errors","_checker","validateWith","_repeat","times","_getPadding","char","padLeft","padRight","repeat","replace","splitBy","_search","search","testWith","pattern","s","isInstanceOf","constructor","isType","typeName"],"sources":["lamb.mjs"],"mappings":"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","sourcesContent":["/**\n* @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming.\n* @author Andrea Scartabelli <andrea.scartabelli@gmail.com>\n* @version 0.61.1\n* @module lamb\n* @license MIT\n*/\n/**\n * The placeholder object used in partial application.\n * @memberof module:lamb\n * @alias module:lamb.__\n * @category Special properties\n * @see {@link module:lamb.partial|partial}, {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.asPartial|asPartial}\n * @since 0.57.0\n * @type {Object}\n */\nvar __ = {};\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 * const 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 * const foo = {bar: \"baz\"};\n * const alwaysFoo = _.always(foo);\n *\n * alwaysFoo() === foo // => true\n *\n * @memberof module:lamb\n * @category Function\n * @see [SKI combinator calculus]{@link https://en.wikipedia.org/wiki/SKI_combinator_calculus}\n * @since 0.1.0\n * @param {*} value\n * @returns {Function}\n */\nfunction always (value) {\n    return function () {\n        return value;\n    };\n}\n\n/**\n * Verifies that the two supplied values are the same value using the \"SameValueZero\" comparison.<br/>\n * With this comparison <code>NaN</code> is equal to itself, but <code>0</code> and <code>-0</code> are\n * considered the same value.<br/>\n * See also {@link module:lamb.isSVZ|isSVZ} for a curried version building a predicate and\n * {@link module:lamb.areSame|areSame} and {@link module:lamb.is|is} to perform a \"SameValue\" comparison.\n * @example\n * const testObject = {};\n *\n * _.areSVZ({}, testObject) // => false\n * _.areSVZ(testObject, testObject) // => true\n * _.areSVZ(\"foo\", \"foo\") // => true\n * _.areSVZ(0, -0) // => true\n * _.areSVZ(0 / 0, NaN) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.isSVZ|isSVZ}\n * @see {@link module:lamb.areSame|areSame}, {@link module:lamb.is|is}\n * @see [SameValue comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevaluezero}\n * @since 0.50.0\n * @param {*} a\n * @param {*} b\n * @returns {Boolean}\n */\nfunction areSVZ (a, b) {\n    return a !== a ? b !== b : a === b; // eslint-disable-line no-self-compare\n}\n\n/**\n * Builds a function that passes only two arguments to the given function.<br/>\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.\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 * @see {@link module:lamb.aritize|aritize}\n * @see {@link module:lamb.unary|unary}\n * @since 0.10.0\n * @param {Function} fn\n * @returns {Function}\n */\nfunction binary (fn) {\n    return function (a, b) {\n        return fn.call(this, a, b);\n    };\n}\n\n/**\n * \"Clamps\" a number within the given limits, both included.<br/>\n * The function will convert to number all its parameters before starting any\n * evaluation, and will return <code>NaN</code> if <code>min</code> is greater\n * than <code>max</code>.\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 * _.clamp(10, 20, 15) // => NaN\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.clampWithin|clampWithin}\n * @since 0.13.0\n * @param {Number} n\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\nfunction clamp (n, min, max) {\n    n = +n;\n    min = +min;\n    max = +max;\n\n    if (min > max) {\n        return NaN;\n    } else {\n        return n < min ? min : n > max ? max : n;\n    }\n}\n\n/**\n * Builds a partially applied function.<br/>\n * The {@link module:lamb.__|__} object can be used as a placeholder for arguments.<br/>\n * @example\n * const __ = _.__;\n * const users = [\n *     {id: 1, name: \"John\", active: true, confirmedMail: true},\n *     {id: 2, name: \"Jane\", active: true, confirmedMail: false},\n *     {id: 3, name: \"Mario\", active: false, confirmedMail: false}\n * ];\n * const isKeyTrue = _.partial(_.hasKeyValue, [__, true]);\n * const isActive = isKeyTrue(\"active\");\n * const hasConfirmedMail = isKeyTrue(\"confirmedMail\");\n *\n * _.map(users, isActive) // => [true, true, false]\n * _.map(users, hasConfirmedMail) // => [true, false, false]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.asPartial|asPartial}\n * @see {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight}\n * @see {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * @see {@link module:lamb.__|__} The placeholder object.\n * @since 0.1.0\n * @param {Function} fn\n * @param {Array} args\n * @returns {Function}\n */\nfunction partial (fn, args) {\n    return function () {\n        if (!Array.isArray(args)) {\n            return fn.apply(this, arguments);\n        }\n\n        var lastIdx = 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[lastIdx++] : boundArg;\n        }\n\n        for (var len = arguments.length; lastIdx < len; lastIdx++) {\n            newArgs[i++] = arguments[lastIdx];\n        }\n\n        return fn.apply(this, newArgs);\n    };\n}\n\n/**\n * Builds a partial application of a ternary function so that its first parameter\n * is expected as the last one.<br/>\n * The <code>shouldAritize</code> parameter is for the \"reduce\" functions, where\n * the absence of the <code>initialValue</code> transforms a \"fold\" operation into a\n * \"reduce\" one.\n * @private\n * @param {Function} fn\n * @param {Boolean} shouldAritize\n * @returns {Function}\n */\nfunction _makePartial3 (fn, shouldAritize) {\n    return function (a, b) {\n        var f = shouldAritize && arguments.length !== 2 ? binary(fn) : fn;\n\n        return partial(f, [__, a, b]);\n    };\n}\n\n/**\n * A curried version of {@link module:lamb.clamp|clamp}, expecting a <code>min</code>\n * and a <code>max</code> value, that builds a function waiting for the number to clamp.\n * @example\n * _.clampWithin(0, 10)(-5) // => 0\n * _.clampWithin(0, 10)(5) // => 5\n * _.clampWithin(0, 10)(15) // => 10\n * _.clampWithin(0, 10)(0) // => 0\n * _.clampWithin(0, 10)(10) // => 10\n * _.is(_.clampWithin(0, 10)(-0), -0) // => true\n * _.clampWithin(20, 15)(10) // => NaN\n *\n * @memberof module:lamb\n * @category Math\n * @function\n * @see {@link module:lamb.clamp|clamp}\n * @since 0.47.0\n * @param {Number} min\n * @param {Number} max\n * @returns {Function}\n */\nvar clampWithin = _makePartial3(clamp);\n\n/**\n * The I combinator. Any value passed to the function is simply returned as it is.\n * @example\n * const foo = {bar: \"baz\"};\n *\n * _.identity(foo) === foo // true\n *\n * @memberof module:lamb\n * @category Function\n * @see [SKI combinator calculus]{@link https://en.wikipedia.org/wiki/SKI_combinator_calculus}\n * @since 0.1.0\n * @param {*} value\n * @returns {*} The value passed as parameter.\n */\nfunction identity (value) {\n    return value;\n}\n\n/**\n * Returns a function that is the composition of the functions given as parameters.\n * The first function consumes the result of the function that follows.\n * @example\n * const sayHi = name => `Hi, ${name}`;\n * const capitalize = s => s[0].toUpperCase() + s.substring(1).toLowerCase();\n * const fixNameAndSayHi = _.compose(sayHi, capitalize);\n *\n * sayHi(\"bOb\") // => \"Hi, bOb\"\n * fixNameAndSayHi(\"bOb\") // \"Hi, Bob\"\n *\n * const users = [{name: \"fred\"}, {name: \"bOb\"}];\n * const sayHiToUser = _.compose(fixNameAndSayHi, _.getKey(\"name\"));\n *\n * _.map(users, sayHiToUser) // [\"Hi, Fred\", \"Hi, Bob\"]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.pipe|pipe}\n * @since 0.1.0\n * @param {Function} a\n * @param {Function} b\n * @returns {Function}\n */\nfunction compose (a, b) {\n    return arguments.length ? function () {\n        return a.call(this, b.apply(this, arguments));\n    } : identity;\n}\n\nvar MAX_ARRAY_LENGTH = 4294967295;\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Converts a value to a valid array length, thus an integer within\n * <code>0</code> and <code>2<sup>32</sup> - 1</code> (both included).\n * @private\n * @param {*} value\n * @returns {Number}\n */\nfunction _toArrayLength (value) {\n    return clamp(value, 0, MAX_ARRAY_LENGTH) >>> 0;\n}\n\n/* eslint-disable jsdoc/require-returns-check */\n\n/**\n * Executes the provided <code>iteratee</code> for each element of the given array-like object.<br/>\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example <caption>Adding a CSS class to all elements of a NodeList in a browser environment:</caption>\n * const addClass = _.curry(function (className, element) {\n *     element.classList.add(className);\n * });\n * const 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 * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @returns {Undefined}\n */\nfunction forEach (arrayLike, iteratee) {\n    for (var i = 0, len = _toArrayLength(arrayLike.length); i < len; i++) {\n        iteratee(arrayLike[i], i, arrayLike);\n    }\n}\n\n/**\n * Creates generic functions out of methods.\n * @author A very little change on a great idea by [Irakli Gozalishvili]{@link https://github.com/Gozala/}.\n * Thanks for this *beautiful* one-liner (never liked your \"unbind\" naming choice, though).\n * @memberof module:lamb\n * @category Function\n * @function\n * @example\n * const join = _.generic(Array.prototype.join);\n *\n * join([1, 2, 3, 4, 5], \"-\") // => \"1-2-3-4-5\"\n *\n * // the function will work with any array-like object\n * join(\"hello\", \"-\") // => \"h-e-l-l-o\"\n *\n * @since 0.1.0\n * @param {Function} method\n * @returns {Function}\n */\nvar generic = Function.bind.bind(Function.call);\n\n/**\n * Verifies if a value is <code>null</code>.\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 <code>undefined</code> too.\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isNull (value) {\n    return value === null;\n}\n\n/**\n * Verifies if a value is <code>undefined</code>.\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 <code>null</code> too.\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isUndefined (value) {\n    return value === void 0;\n}\n\n/**\n * Verifies if a value is <code>null</code> or <code>undefined</code>.\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}\n * @see {@link module:lamb.isUndefined|isUndefined}\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isNil (value) {\n    return isNull(value) || isUndefined(value);\n}\n\n/**\n * Curries a function of arity 2.\n * @private\n * @param {Function} fn\n * @param {Boolean} [isRightCurry=false]\n * @returns {Function}\n */\nfunction _curry2 (fn, isRightCurry) {\n    return function (a) {\n        return function (b) {\n            return isRightCurry ? fn.call(this, b, a) : fn.call(this, a, b);\n        };\n    };\n}\n\n/**\n * A curried version of {@link module:lamb.areSVZ|areSVZ}.<br/>\n * Accepts a value and builds a predicate that checks whether the value\n * and the one received by the predicate are the same using the \"SameValueZero\"\n * comparison.<br/>\n * See also {@link module:lamb.areSame|areSame} and {@link module:lamb.is|is}\n * to perform a \"SameValue\" comparison.\n * @example\n * const john = {name: \"John\", surname: \"Doe\"};\n * const isJohn = _.isSVZ(john);\n * const isZero = _.isSVZ(0);\n * const isReallyNaN = _.isSVZ(NaN);\n *\n * isJohn(john) // => true\n * isJohn({name: \"John\", surname: \"Doe\"}) // => false\n *\n * isZero(0) // => true\n * isZero(-0) // => true\n *\n * isNaN(NaN) // => true\n * isNaN(\"foo\") // => true\n *\n * isReallyNaN(NaN) // => true\n * isReallyNaN(\"foo\") // => false\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.areSVZ|areSVZ}\n * @see {@link module:lamb.areSame|areSame}, {@link module:lamb.is|is}\n * @see [SameValue comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevaluezero}\n * @since 0.1.0\n * @param {*} value\n * @returns {Function}\n */\nvar isSVZ = _curry2(areSVZ);\n\n/**\n * Builds a new array by applying the iteratee function to each element of the\n * received array-like object.<br/>\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * _.map([\"Joe\", \"Mario\", \"Jane\"], _.invoke(\"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 * @see {@link module:lamb.flatMap|flatMap}, {@link module:lamb.flatMapWith|flatMapWith}\n * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @returns {Array}\n */\nfunction map (arrayLike, iteratee) {\n    var len = _toArrayLength(arrayLike.length);\n    var result = Array(len);\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 * A curried version of {@link module:lamb.map|map} that uses the provided iteratee to\n * build a function expecting the array-like object to act upon.\n * @example\n * const square = n => n ** 2;\n * const 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 * @see {@link module:lamb.flatMap|flatMap}, {@link module:lamb.flatMapWith|flatMapWith}\n * @since 0.1.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nvar mapWith = _curry2(map, true);\n\n/**\n * Like {@link module:lamb.partial|partial} will build a partially applied function and\n * it will accept placeholders.<br/>\n * The difference is that the bound arguments will be appended to the ones received by\n * the resulting function.\n * @example\n * <caption>Explaining the difference with <code>partial</code>:</caption>\n * const f1 = _.partial(_.list, [\"a\", \"b\", \"c\"]);\n * const f2 = _.partialRight(_.list, [\"a\", \"b\", \"c\"]);\n *\n * f1(\"d\", \"e\") // => [\"a\", \"b\", \"c\", \"d\", \"e\"]\n * f2(\"d\", \"e\") // => [\"d\", \"e\", \"a\", \"b\", \"c\"]\n *\n * @example\n * <caption>Explaining placeholder substitutions:</caption>\n * const __ = _.__;\n * const f1 = _.partial(_.list, [\"a\", __, __, \"d\"]);\n * const f2 = _.partialRight(_.list, [\"a\", __, __, \"d\"]);\n *\n * f1(\"b\", \"c\", \"e\") // => [\"a\", \"b\", \"c\", \"d\", \"e\"]\n * f2(\"b\", \"c\", \"e\") // => [\"b\", \"a\", \"c\", \"e\", \"d\"]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.partial|partial}\n * @see {@link module:lamb.asPartial|asPartial}\n * @see {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight}\n * @see {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * @see {@link module:lamb.__|__} The placeholder object.\n * @param {Function} fn\n * @param {Array} args\n * @since 0.52.0\n * @returns {Function}\n */\nfunction partialRight (fn, args) {\n    return function () {\n        if (!Array.isArray(args)) {\n            return fn.apply(this, arguments);\n        }\n\n        var lastIdx = arguments.length - 1;\n        var argsLen = args.length;\n        var boundArgs = Array(argsLen);\n        var newArgs = [];\n\n        for (var i = argsLen - 1, boundArg; i > -1; i--) {\n            boundArg = args[i];\n            boundArgs[i] = boundArg === __ ? arguments[lastIdx--] : boundArg;\n        }\n\n        for (i = 0; i <= lastIdx; i++) {\n            newArgs[i] = arguments[i];\n        }\n\n        for (var j = 0; j < argsLen; j++) {\n            newArgs[i++] = boundArgs[j];\n        }\n\n        return fn.apply(this, newArgs);\n    };\n}\n\n/**\n * Builds a reduce function. The <code>step</code> parameter must be <code>1</code>\n * to build  {@link module:lamb.reduce|reduce} and <code>-1</code> to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\nfunction _makeReducer (step) {\n    return function (arrayLike, accumulator, initialValue) {\n        var len = _toArrayLength(arrayLike.length);\n        var idx = step === 1 ? 0 : len - 1;\n        var nCalls;\n        var result;\n\n        if (arguments.length < 3) {\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        } else {\n            nCalls = len;\n            result = initialValue;\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 * Reduces (or folds) the values of an array-like object, starting from the first, to a new\n * value using the provided <code>accumulator</code> function.<br/>\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], _.sum) // => 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 * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {*}\n */\nvar reduce = _makeReducer(1);\n\n/**\n * A partial application of {@link module:lamb.reduce|reduce} that uses the\n * provided <code>accumulator</code> and the optional <code>initialValue</code> to\n * build a function expecting the array-like object to act upon.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.reduceWith(_.sum)(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 * @since 0.27.0\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {Function}\n */\nvar reduceWith = _makePartial3(reduce, true);\n\n/**\n * Converts a value to an integer.\n * @private\n * @param {*} value\n * @returns {Number}\n */\nfunction _toInteger (value) {\n    var n = +value;\n\n    if (n !== n) { // eslint-disable-line no-self-compare\n        return 0;\n    } else if (n % 1 === 0) {\n        return n;\n    } else {\n        return Math.floor(Math.abs(n)) * (n < 0 ? -1 : 1);\n    }\n}\n\n/**\n * Builds an array by extracting a portion of an array-like object.<br/>\n * Note that unlike the native array method this function ensures that dense\n * arrays are returned.<br/>\n * Also, unlike the native method, the <code>start</code> and <code>end</code>\n * parameters aren't optional and will be simply converted to integer.<br/>\n * See {@link module:lamb.dropFrom|dropFrom} and {@link module:lamb.drop|drop} if you want a\n * slice to the end of the array-like.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.slice(arr, 0, 2) // => [1, 2]\n * _.slice(arr, 2, -1) // => [3, 4]\n * _.slice(arr, -3, 5) // => [3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.sliceAt|sliceAt}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @since 0.1.0\n * @param {ArrayLike} arrayLike - Any array like object.\n * @param {Number} start - Index at which to begin extraction.\n * @param {Number} end - Index at which to end extraction. Extracts up to but not including end.\n * @returns {Array}\n */\nfunction slice (arrayLike, start, end) {\n    var len = _toArrayLength(arrayLike.length);\n    var begin = _toInteger(start);\n    var upTo = _toInteger(end);\n\n    if (begin < 0) {\n        begin = begin < -len ? 0 : begin + len;\n    }\n\n    if (upTo < 0) {\n        upTo = upTo < -len ? 0 : upTo + len;\n    } else if (upTo > len) {\n        upTo = len;\n    }\n\n    var resultLen = upTo - begin;\n    var result = resultLen > 0 ? Array(resultLen) : [];\n\n    for (var i = 0; i < resultLen; i++) {\n        result[i] = arrayLike[begin + i];\n    }\n\n    return result;\n}\n\n/**\n * Given the <code>start</code> and <code>end</code> bounds, builds a partial application\n * of {@link module:lamb.slice|slice} expecting the array-like object to slice.<br/>\n * See also {@link module:lamb.dropFrom|dropFrom} and {@link module:lamb.drop|drop} if you want a\n * slice to the end of the array-like.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n * const s = \"hello\";\n * const dropFirstAndLast = _.sliceAt(1, -1);\n *\n * dropFirstAndLast(arr) // => [2, 3, 4]\n * dropFirstAndLast(s) // => [\"e\", \"l\", \"l\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.slice|slice}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @since 0.48.0\n * @param {Number} start - Index at which to begin extraction.\n * @param {Number} end - Index at which to end extraction. Extracts up to but not including end.\n * @returns {Function}\n */\nvar sliceAt = _makePartial3(slice);\n\nvar objectProtoToString = Object.prototype.toString;\n\n/**\n * Retrieves the \"type tag\" from the given value.\n * @example\n * const x = 5;\n * const 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 * @since 0.9.0\n * @param {*} value\n * @returns {String}\n */\nfunction type (value) {\n    return objectProtoToString.call(value).slice(8, -1);\n}\n\n/**\n * Appends the given value at the end of a copy of the provided array-like object.\n * @example\n * const arr = [1, 2, 3, 4];\n *\n * _.appendTo(arr, 5) // => [1, 2, 3, 4, 5]\n * _.appendTo(arr, [5]) // => [1, 2, 3, 4, [5]]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.append|append}\n * @see {@link module:lamb.insert|insert}, {@link module:lamb.insertAt|insertAt}\n * @since 0.44.0\n * @param {ArrayLike} arrayLike\n * @param {*} value\n * @returns {Array}\n */\nfunction appendTo (arrayLike, value) {\n    return slice(arrayLike, 0, arrayLike.length).concat([value]);\n}\n\n/**\n * A curried version of {@link module:lamb.appendTo|appendTo} that uses the value to append\n * to build a function expecting the array-like object to act upon.\n * @example\n * const arr = [1, 2, 3, 4];\n *\n * _.append(5)(arr) // => [1, 2, 3, 4, 5]\n * _.append([5])(arr) // => [1, 2, 3, 4, [5]]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.appendTo|appendTo}\n * @see {@link module:lamb.insert|insert}, {@link module:lamb.insertAt|insertAt}\n * @since 0.44.0\n * @param {*} value\n * @returns {Function}\n */\nvar append = _curry2(appendTo, true);\n\n/**\n * Checks if an array-like object contains the given value.<br/>\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for <code>NaN</code>, but <code>0</code> and <code>-0</code> are the same value.<br/>\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * const 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, 5) // => false\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.contains|contains}\n * @since 0.13.0\n * @param {ArrayLike} arrayLike\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isIn (arrayLike, value) {\n    var result = false;\n\n    for (var i = 0, len = arrayLike.length; i < len; i++) {\n        if (areSVZ(value, arrayLike[i])) {\n            result = true;\n            break;\n        }\n    }\n\n    return result;\n}\n\n/**\n * Builds a predicate to check if an array-like object contains the given value.<br/>\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for <code>NaN</code>, but <code>0</code> and <code>-0</code> are the same value.<br/>\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * const containsNaN = _.contains(NaN);\n *\n * containsNaN([0, 1, 2, 3, NaN]) // => true\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.isIn|isIn}\n * @since 0.13.0\n * @param {*} value\n * @returns {Function}\n */\nvar contains = _curry2(isIn, true);\n\n/**\n * Builds a \"grouping function\" for an array-like object.\n * @private\n * @param {Function} makeValue\n * @returns {Function}\n */\nfunction _groupWith (makeValue) {\n    return function (arrayLike, iteratee) {\n        var result = {};\n        var len = arrayLike.length;\n\n        for (var i = 0, element, key; i < len; i++) {\n            element = arrayLike[i];\n            key = iteratee(element, i, arrayLike);\n            result[key] = makeValue(result[key], element);\n        }\n\n        return result;\n    };\n}\n\n/**\n * Transforms an array-like object in a lookup table with the keys generated by the provided\n * <code>iteratee</code>, having as values the count of matches for the key.\n * @example\n * const persons = [\n *     {\"name\": \"Jane\", \"age\": 12},\n *     {\"name\": \"John\", \"age\": 40},\n *     {\"name\": \"Mario\", \"age\": 17},\n *     {\"name\": \"Paolo\", \"age\": 15}\n * ];\n * const getAgeStatus = person => (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 * @since 0.21.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @returns {Object}\n */\nvar count = _groupWith(function (a) {\n    return a ? ++a : 1;\n});\n\n/**\n * A curried version of {@link module:lamb.count|count} that uses the provided iteratee to\n * build a function expecting the array-like object to act upon.\n * @example\n * const persons = [\n *     {\"name\": \"Jane\", \"city\": \"New York\"},\n *     {\"name\": \"John\", \"city\": \"New York\"},\n *     {\"name\": \"Mario\", \"city\": \"Rome\"},\n *     {\"name\": \"Paolo\"}\n * ];\n * const getCityOrUnknown = _.adapter([_.getKey(\"city\"), _.always(\"Unknown\")]);\n * const 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 * @since 0.21.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nvar countBy = _curry2(count, true);\n\nvar nativeSlice = generic(Array.prototype.slice);\n\n/**\n * Utility function to check whether the passed value is\n * an Array or an \"array-like\" object.\n * @private\n * @param {*} target\n * @returns {Boolean}\n */\nfunction _isArrayLike (target) {\n    var len = target ? target.length : NaN;\n\n    return Array.isArray(target) || len === 0 || (\n        typeof len === \"number\"\n            && len > 0\n            && (len - 1) in Object(target)\n    );\n}\n\n/**\n * Helper object to have faster lookups if the environment\n * supports Sets.\n * @class\n * @private\n * @param {ArrayLike} [arrayLike]\n */\nfunction _LookupHelper (arrayLike) {\n    var hasNativeSet = typeof Set === \"function\";\n    var sourceElements = Array.isArray(arrayLike)\n        ? arrayLike\n        : _isArrayLike(arrayLike)\n            ? nativeSlice(arrayLike)\n            : [];\n\n    /* eslint-disable-next-line no-undef */\n    var sourceElementsSet = hasNativeSet ? new Set(sourceElements) : null;\n\n    this.add = function (value) {\n        if (hasNativeSet) {\n            sourceElementsSet.add(value);\n        } else {\n            sourceElements.push(value);\n        }\n\n        return this;\n    };\n\n    this.has = function (value) {\n        return hasNativeSet\n            ? sourceElementsSet.has(value)\n            : isIn(sourceElements, value);\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 */\nfunction _makeTypeErrorFor (value, desiredType) {\n    return new TypeError(\"Cannot convert \" + type(value).toLowerCase() + \" to \" + desiredType);\n}\n\n/**\n * Builds an array comprised of all values of the array-like object passing the <code>predicate</code>\n * test.<br/>\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example\n * const isLowerCase = s => 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 * @since 0.1.0\n * @returns {Array}\n */\nfunction filter (arrayLike, predicate) {\n    var len = arrayLike.length;\n    var result = [];\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 * Using the provided iteratee, builds a function that will return an array comprised of the\n * unique elements of an array-like object. The values being compared are the ones returned by\n * the iteratee.<br/>\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.<br/>\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.<br/>\n * See also {@link module:lamb.uniques|uniques} if you don't need to transform your values before the\n * comparison.\n * @example\n * const data  = [\n *     {id: \"1\", name: \"John\"},\n *     {id: \"4\", name: \"Jane\"},\n *     {id: \"5\", name: \"Joe\"},\n *     {id: \"1\", name: \"Mario\"},\n *     {id: \"5\", name: \"Paolo\"},\n * ];\n * const uniquesById = _.uniquesBy(_.getKey(\"id\"));\n *\n * uniquesById(data) // => [{id: \"1\", name: \"John\"}, {id: \"4\", name: \"Jane\"}, {id: \"5\", name: \"Joe\"}]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.uniques|uniques}\n * @since 0.51.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nfunction uniquesBy (iteratee) {\n    return function (arrayLike) {\n        var result = [];\n\n        for (var i = 0, len = arrayLike.length, seen = new _LookupHelper(), value; i < len; i++) {\n            value = iteratee(arrayLike[i], i, arrayLike);\n\n            if (!seen.has(value)) {\n                seen.add(value);\n                result.push(arrayLike[i]);\n            }\n        }\n\n        return result;\n    };\n}\n\n/**\n * Returns an array comprised of the unique elements of the given array-like object.<br/>\n * Note that this function uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.<br/>\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.<br/>\n * See also {@link module:lamb.uniquesBy|uniquesBy} if you need to transform your values before\n * the comparison or if you have to extract them from complex ones.\n * @example\n * _.uniques([-0, 1, 2, 0, 2, 3, 4, 3, 5, 1]) // => [-0, 1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.uniquesBy|uniquesBy}\n * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\nvar uniques = uniquesBy(identity);\n\n/**\n * Returns an array of unique items present only in the first of the two given\n * array-like objects. To determine uniqueness the function uses the\n * [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.\n * @example\n * const a1 = [1, 2, 1, 3, 4];\n * const a2 = [2, 4, 5, 6];\n * const a3 = [3, 4, 5, 2, 1];\n *\n * _.difference(a1, a2) // => [1, 3]\n * _.difference(a2, a3) // => [6]\n * _.difference(a1, a3) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.intersection|intersection}\n * @see {@link module:lamb.symmetricDifference|symmetricDifference}\n * @see {@link module:lamb.union|union}, {@link module:lamb.unionBy|unionBy}\n * @see {@link module:lamb.pull|pull}, {@link module:lamb.pullFrom|pullFrom}\n * @since 0.6.0\n * @param {ArrayLike} a\n * @param {ArrayLike} b\n * @returns {Array}\n */\nfunction difference (a, b) {\n    if (isNil(b)) {\n        throw _makeTypeErrorFor(b, \"array\");\n    }\n\n    var toExclude = new _LookupHelper(b);\n    var isNotInB = function (v) {\n        return !toExclude.has(v);\n    };\n\n    return uniques(filter(a, isNotInB));\n}\n\n/**\n * Builds an array without the first <code>n</code> 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 * <code>n</code> can be a negative number.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.dropFrom(arr, 2) // => [3, 4, 5]\n * _.dropFrom(arr, -1) // => [5]\n * _.dropFrom(arr, -10) // => [1, 2, 3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.drop|drop}\n * @see {@link module:lamb.takeFrom|takeFrom}, {@link module:lamb.take|take}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropLastWhile|dropLastWhile}\n * @since 0.51.0\n * @param {ArrayLike} arrayLike\n * @param {Number} n\n * @returns {Array}\n */\nfunction dropFrom (arrayLike, n) {\n    return slice(arrayLike, n, arrayLike.length);\n}\n\n/**\n * A curried version of {@link module:lamb.dropFrom|dropFrom} that expects the number of elements\n * to drop to build a function waiting for the list to take the elements from.<br/>\n * See the note and examples for {@link module:lamb.dropFrom|dropFrom} about passing a\n * negative <code>n</code>.\n * @example\n * const drop2 = _.drop(2);\n *\n * drop2([1, 2, 3, 4, 5]) // => [3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @since 0.5.0\n * @see {@link module:lamb.dropFrom|dropFrom}\n * @see {@link module:lamb.takeFrom|takeFrom}, {@link module:lamb.take|take}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropLastWhile|dropLastWhile}\n * @param {Number} n\n * @returns {Function}\n */\nvar drop = _curry2(dropFrom, true);\n\n/**\n * Gets the index of the last element satisfying a predicate in an array-like object.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Boolean} fromLast\n * @returns {Number}\n */\nfunction _getLastHitIndex (arrayLike, predicate, fromLast) {\n    var idx;\n    var increment;\n    var len = arrayLike.length;\n\n    if (fromLast) {\n        idx = len - 1;\n        increment = -1;\n    } else {\n        idx = 0;\n        increment = 1;\n    }\n\n    while (idx >= 0 && idx < len && predicate(arrayLike[idx], idx, arrayLike)) {\n        idx += increment;\n    }\n\n    return idx;\n}\n\n/**\n * Helper to build the {@link module:lamb.takeWhile|takeWhile},\n * {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropWhile|dropWhile} and\n * {@link module:lamb.dropLastWhile|dropLastWhile} functions.\n * @private\n * @param {Boolean} isTake\n * @param {Boolean} fromLast\n * @returns {Function}\n */\nfunction _takeOrDropWhile (isTake, fromLast) {\n    return function (predicate) {\n        return function (arrayLike) {\n            var idxFrom;\n            var idxTo;\n            var lastHitIndex = _getLastHitIndex(arrayLike, predicate, fromLast);\n\n            if (isTake && fromLast) {\n                idxFrom = lastHitIndex + 1;\n                idxTo = arrayLike.length;\n            } else if (isTake) {\n                idxFrom = 0;\n                idxTo = lastHitIndex;\n            } else if (!isTake && fromLast) {\n                idxFrom = 0;\n                idxTo = lastHitIndex + 1;\n            } else {\n                idxFrom = lastHitIndex;\n                idxTo = arrayLike.length;\n            }\n\n            return slice(arrayLike, idxFrom, idxTo);\n        };\n    };\n}\n\n/**\n * Builds a function that drops the last elements satisfying a predicate\n * from an array or array-like object.\n * @example\n * const isEven = n => n % 2 === 0;\n * const dropLastWhileIsEven = _.dropLastWhile(isEven);\n *\n * dropLastWhileIsEven([2, 4, 6, 8]) // => []\n * dropLastWhileIsEven([2, 4, 7, 8]) // => [2, 4, 7]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @see {@link module:lamb.takeFrom|takeFrom}, {@link module:lamb.take|take}\n * @since 0.58.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar dropLastWhile = _takeOrDropWhile(false, true);\n\n/**\n * Builds a function that drops the first elements satisfying a predicate\n * from an array or array-like object.\n * @example\n * const isEven = n => n % 2 === 0;\n * const 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 * @function\n * @see {@link module:lamb.takeWhile|takeWhile}\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropLastWhile|dropLastWhile}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @see {@link module:lamb.takeFrom|takeFrom}, {@link module:lamb.take|take}\n * @since 0.5.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar dropWhile = _takeOrDropWhile(false, false);\n\n/**\n * Helper to build the {@link module:lamb.everyIn|everyIn} or the\n * {@link module:lamb.someIn|someIn} function.\n * @private\n * @param {Boolean} defaultResult\n * @returns {Function}\n */\nfunction _makeArrayChecker (defaultResult) {\n    return function (arrayLike, predicate) {\n        for (var i = 0, len = arrayLike.length; i < len; i++) {\n            if (defaultResult ^ !!predicate(arrayLike[i], i, arrayLike)) {\n                return !defaultResult;\n            }\n        }\n\n        return defaultResult;\n    };\n}\n\n/**\n * Checks if all the elements in an array-like object satisfy the given predicate.<br/>\n * The function will stop calling the predicate as soon as it returns a <em>falsy</em> value.<br/>\n * Note that an empty array-like will always produce a <code>true</code> result regardless of the\n * predicate because of [vacuous truth]{@link https://en.wikipedia.org/wiki/Vacuous_truth}.<br/>\n * Also note that unlike the native\n * [Array.prototype.every]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every},\n * this function won't skip deleted or unassigned indexes.\n * @example\n * const persons = [\n *     {\"name\": \"Jane\", \"age\": 12, active: true},\n *     {\"name\": \"John\", \"age\": 40, active: true},\n *     {\"name\": \"Mario\", \"age\": 17, active: true},\n *     {\"name\": \"Paolo\", \"age\": 15, active: true}\n * ];\n * const isAdult = _.keySatisfies(_.isGTE(18), \"age\");\n * const isActive = _.hasKeyValue(\"active\", true);\n *\n * _.everyIn(persons, isAdult) // => false\n * _.everyIn(persons, isActive) // => true\n *\n * @example <caption>Showing the difference with <code>Array.prototype.every</code>:</caption>\n * const isDefined = _.not(_.isUndefined);\n * const arr = new Array(5);\n * arr[3] = 99;\n *\n * arr.every(isDefined) // => true\n * _.everyIn(arr, isDefined) // => false\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.every|every}\n * @see {@link module:lamb.some|some}, {@link module:lamb.someIn|someIn}\n * @since 0.39.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {Boolean}\n */\nvar everyIn = _makeArrayChecker(true);\n\n/**\n * A curried version of {@link module:lamb.everyIn|everyIn} that expects a predicate\n * to build a function waiting for the array-like to act upon.\n * @example\n * const data = [2, 3, 5, 6, 8];\n * const isEven = n => n % 2 === 0;\n * const allEvens = _.every(isEven);\n * const allIntegers = _.every(_.isInteger);\n *\n * allEvens(data) // => false\n * allIntegers(data) // => true\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.everyIn|everyIn}\n * @see {@link module:lamb.some|some}, {@link module:lamb.someIn|someIn}\n * @since 0.39.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar every = _curry2(everyIn, true);\n\n/**\n * A curried version of {@link module:lamb.filter|filter} that uses the given predicate\n * to build a function expecting the array-like object to act upon.\n * @example\n * const isLowerCase = s => s.toLowerCase() === s;\n * const 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 * @since 0.9.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar filterWith = _curry2(filter, true);\n\n/**\n * Helper to create the {@link module:lamb.findIndex|findIndex} and\n * {@link module:lamb.findLastIndex|findLastIndex} functions.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @param {Boolean} fromLast\n * @returns {Number}\n */\nfunction _findIndex (arrayLike, predicate, fromLast) {\n    var start;\n    var increment;\n    var len = arrayLike.length;\n    var result = -1;\n\n    if (fromLast) {\n        start = len - 1;\n        increment = -1;\n    } else {\n        start = 0;\n        increment = 1;\n    }\n\n    for (var i = start; i < len && i >= 0; i += increment) {\n        if (predicate(arrayLike[i], i, arrayLike)) {\n            result = i;\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 <code>-1</code> otherwise.\n * @example\n * const 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 * @see {@link module:lamb.findIndexWhere|findIndexWhere}\n * @see {@link module:lamb.find|find}, {@link module:lamb.findWhere|findWhere}\n * @see {@link module:lamb.findLastIndex|findLastIndex},\n *      {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @see {@link module:lamb.findLast|findLast}, {@link module:lamb.findLastWhere|findLastWhere}\n * @since 0.7.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {Number}\n */\nfunction findIndex (arrayLike, predicate) {\n    return _findIndex(arrayLike, predicate, false);\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 <code>undefined</code> otherwise.\n * @example\n * const 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 * @see {@link module:lamb.findWhere|findWhere}\n * @see {@link module:lamb.findIndex|findIndex}, {@link module:lamb.findIndexWhere|findIndexWhere}\n * @see {@link module:lamb.findLast|findLast}, {@link module:lamb.findLastWhere|findLastWhere}\n * @see {@link module:lamb.findLastIndex|findLastIndex},\n *      {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @since 0.7.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {*}\n */\nfunction find (arrayLike, predicate) {\n    var idx = findIndex(arrayLike, predicate);\n\n    return idx === -1 ? void 0 : arrayLike[idx];\n}\n\n/**\n * A curried version of {@link module:lamb.findIndex|findIndex} that uses the given predicate\n * to build a function expecting the array-like object to search.\n * @example\n * const isEven = n => n % 2 === 0;\n * const findEvenIdx = _.findIndexWhere(isEven);\n *\n * findEvenIdx([1, 3, 4, 5, 6, 7]) // => 2\n * findEvenIdx([1, 3, 5, 7]) // => -1\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.findIndex|findIndex}\n * @see {@link module:lamb.find|find}, {@link module:lamb.findWhere|findWhere}\n * @see {@link module:lamb.findLastIndex|findLastIndex},\n *      {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @see {@link module:lamb.findLast|findLast}, {@link module:lamb.findLastWhere|findLastWhere}\n * @since 0.41.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar findIndexWhere = _curry2(findIndex, true);\n\n/**\n * Searches for an element satisfying the predicate in the given array-like object starting from\n * the end and returns its index if the search is successful. Returns <code>-1</code> otherwise.\n * @example\n * const 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 * _.findLastIndex(persons, _.hasKeyValue(\"age\", 40)) // => 3\n * _.findLastIndex(persons, _.hasKeyValue(\"age\", 41)) // => -1\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @see {@link module:lamb.findLast|findLast}, {@link module:lamb.findLastWhere|findLastWhere}\n * @see {@link module:lamb.findIndex|findIndex}, {@link module:lamb.findIndexWhere|findIndexWhere}\n * @see {@link module:lamb.find|find}, {@link module:lamb.findWhere|findWhere}\n * @since 0.58.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {Number}\n */\nfunction findLastIndex (arrayLike, predicate) {\n    return _findIndex(arrayLike, predicate, true);\n}\n\n/**\n * Searches for an element satisfying the predicate in the given array-like object starting from the end\n * and returns it if the search is successful. Returns <code>undefined</code> otherwise.\n * @example\n * const 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 * _.findLast(persons, _.hasKeyValue(\"surname\", \"Doe\")) // => {\"name\": \"John\", \"surname\": \"Doe\", \"age\": 40}\n * _.findLast(persons, _.hasKeyValue(\"age\", 41)) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.findLastWhere|findLastWhere}\n * @see {@link module:lamb.findLastIndex|findLastIndex},\n *      {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @see {@link module:lamb.find|find}, {@link module:lamb.findWhere|findWhere}\n * @see {@link module:lamb.findIndex|findIndex}, {@link module:lamb.findIndexWhere|findIndexWhere}\n * @since 0.58.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {*}\n */\nfunction findLast (arrayLike, predicate) {\n    var idx = findLastIndex(arrayLike, predicate);\n\n    return idx === -1 ? void 0 : arrayLike[idx];\n}\n\n/**\n * A curried version of {@link module:lamb.findLastIndex|findLastIndex} that uses the given predicate\n * to build a function expecting the array-like object to search.\n * @example\n * const isEven = n => n % 2 === 0;\n * const findLastEvenIdx = _.findLastIndexWhere(isEven);\n *\n * findLastEvenIdx([1, 3, 4, 5, 6, 7]) // => 4\n * findLastEvenIdx([1, 3, 5, 7]) // => -1\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.findLastIndex|findLastIndex}\n * @see {@link module:lamb.findLast|findLast}, {@link module:lamb.findLastWhere|findLastWhere}\n * @see {@link module:lamb.findIndex|findIndex}, {@link module:lamb.findIndexWhere|findIndexWhere}\n * @see {@link module:lamb.find|find}, {@link module:lamb.findWhere|findWhere}\n * @since 0.58.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar findLastIndexWhere = _curry2(findLastIndex, true);\n\n/**\n * A curried version of {@link module:lamb.findLast|findLast} that uses the given\n * predicate to build a function expecting the array-like object to search.\n * @example\n * const isEven = n => n % 2 === 0;\n * const findEven = _.findLastWhere(isEven);\n *\n * findEven([1, 3, 4, 5, 6, 7]) // => 6\n * findEven([1, 3, 5, 7]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.findLast|findLast}\n * @see {@link module:lamb.findLastIndex|findLastIndex},\n *      {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @see {@link module:lamb.find|find}, {@link module:lamb.findWhere|findWhere}\n * @see {@link module:lamb.findIndex|findIndex}, {@link module:lamb.findIndexWhere|findIndexWhere}\n * @since 0.58.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar findLastWhere = _curry2(findLast, true);\n\n/**\n * A curried version of {@link module:lamb.find|find} that uses the given\n * predicate to build a function expecting the array-like object to search.\n * @example\n * const isEven = n => n % 2 === 0;\n * const findEven = _.findWhere(isEven);\n *\n * findEven([1, 3, 4, 5, 7]) // => 4\n * findEven([1, 3, 5, 7]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.find|find}\n * @see {@link module:lamb.findIndex|findIndex}, {@link module:lamb.findIndexWhere|findIndexWhere}\n * @see {@link module:lamb.findLast|findLast}, {@link module:lamb.findLastWhere|findLastWhere}\n * @see {@link module:lamb.findLastIndex|findLastIndex},\n *      {@link module:lamb.findLastIndexWhere|findLastIndexWhere}\n * @since 0.41.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar findWhere = _curry2(find, true);\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 <caption>Showing the difference with <code>map</code>:</caption>\n * const words = [\"foo\", \"bar\"];\n * const toCharArray = _.splitBy(\"\");\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 * @see {@link module:lamb.flatMapWith|flatMapWith}\n * @see {@link module:lamb.map|map}, {@link module:lamb.mapWith|mapWith}\n * @since 0.1.0\n * @param {Array} array\n * @param {ListIteratorCallback} iteratee\n * @returns {Array}\n */\nfunction flatMap (array, iteratee) {\n    return reduce(array, function (result, el, idx, arr) {\n        var v = iteratee(el, idx, arr);\n\n        if (!Array.isArray(v)) {\n            v = [v];\n        }\n\n        for (var i = 0, len = v.length, rLen = result.length; i < len; i++) {\n            result[rLen + i] = v[i];\n        }\n\n        return result;\n    }, []);\n}\n\n/**\n * A curried version of {@link module:lamb.flatMap|flatMap} that uses provided iteratee\n * to build a function expecting the array to act upon.\n * @example\n * const toCharArray = _.splitBy(\"\");\n * const 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 * @see {@link module:lamb.map|map}, {@link module:lamb.mapWith|mapWith}\n * @since 0.11.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nvar flatMapWith = _curry2(flatMap, true);\n\n/**\n * Flattens an array.\n * @private\n * @param {Array} array - The source array\n * @param {Boolean} isDeep - Whether to perform a deep flattening or not\n * @param {Array} output - An array to collect the result\n * @param {Number} idx - The next index to be filled in the output\n * @returns {Array} The output array filled with the results\n */\nfunction _flatten (array, isDeep, output, idx) {\n    for (var i = 0, len = array.length, value, j, vLen; i < len; i++) {\n        value = array[i];\n\n        if (!Array.isArray(value)) {\n            output[idx++] = value;\n        } else if (isDeep) {\n            _flatten(value, true, output, idx);\n            idx = output.length;\n        } else {\n            vLen = value.length;\n            output.length += vLen;\n\n            for (j = 0; j < vLen; j++) {\n                output[idx++] = value[j];\n            }\n        }\n    }\n\n    return output;\n}\n\n/**\n * Helper to build the {@link module:lamb.flatten|flatten} and\n * {@link module:lamb.shallowFlatten|shallowFlatten} functions.\n * @private\n * @function\n * @param {Boolean} isDeep\n * @returns {Function}\n */\nvar _makeArrayFlattener = _curry2(function (isDeep, array) {\n    return Array.isArray(array) ? _flatten(array, isDeep, [], 0) : slice(array, 0, array.length);\n});\n\n/**\n * Flattens an array.\n * @example <caption>Showing the difference with <code>shallowFlatten</code>:</caption>\n * const 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 * @function\n * @see {@link module:lamb.shallowFlatten|shallowFlatten}\n * @since 0.1.0\n * @param {Array} array\n * @returns {Array}\n */\nvar flatten = _makeArrayFlattener(true);\n\n/**\n * Checks if the given number, even negative, represents an array-like index\n * within the provided length. If so returns its natural number equivalent.<br/>\n * Returns <code>NaN<code> otherwise.\n * @private\n * @param {Number} idx\n * @param {Number} len\n * @returns {Number}\n */\nfunction _toNaturalIndex (idx, len) {\n    idx = _toInteger(idx);\n\n    return idx >= -len && idx < len ? idx < 0 ? idx + len : idx : NaN;\n}\n\n/**\n * Retrieves the element at the given index in an array-like object.<br/>\n * Like {@link module:lamb.slice|slice} the index can be negative.<br/>\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 <code>undefined</code>.<br/>\n * <code>getIndex</code> will throw an exception when receives <code>null</code> or\n * <code>undefined</code> in place of an array-like object, but returns <code>undefined</code>\n * for any other value.\n * @example\n * const 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 * @since 0.23.0\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @returns {*}\n */\nfunction getIndex (arrayLike, index) {\n    var idx = _toNaturalIndex(index, _toArrayLength(arrayLike.length));\n\n    return idx === idx ? arrayLike[idx] : void 0; // eslint-disable-line no-self-compare\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 * const 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 <caption>Using negative indexes:</caption>\n * _.getAt(-2)([1, 2, 3]) // => 2\n * _.getAt(-3)(\"foo\") // => \"f\"\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @since 0.16.0\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 */\nvar getAt = _curry2(getIndex, true);\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 * const persons = [\n *     {\"name\": \"Jane\", \"city\": \"New York\"},\n *     {\"name\": \"John\", \"city\": \"New York\"},\n *     {\"name\": \"Mario\", \"city\": \"Rome\"},\n *     {\"name\": \"Paolo\"}\n * ];\n * const getCity = _.getKey(\"city\");\n * const 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 <caption>Adding a custom value for missing keys:</caption>\n *\n * const getCityOrUnknown = _.adapter([getCity, _.always(\"Unknown\")]);\n *\n * const 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 * @since 0.7.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @returns {Object}\n */\nvar group = _groupWith(function (a, b) {\n    if (!a) {\n        return [b];\n    }\n\n    a[a.length] = b;\n\n    return a;\n});\n\n/**\n * A curried version of {@link module:lamb.group|group} that uses the provided iteratee\n * to build a function expecting the array-like object to act upon.\n * @example\n * const persons = [\n *     {\"name\": \"Jane\", \"age\": 12},\n *     {\"name\": \"John\", \"age\": 40},\n *     {\"name\": \"Mario\", \"age\": 18},\n *     {\"name\": \"Paolo\", \"age\": 15}\n * ];\n *\n * const getAgeStatus = person => `${person.age > 20 ? \"over\" : \"under\"} 20`;\n * const groupByAgeStatus = _.groupBy(getAgeStatus);\n *\n * const 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 * @since 0.7.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nvar groupBy = _curry2(group, true);\n\n/**\n * Retrieves the first element of an array-like object.<br/>\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 * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\nvar head = getAt(0);\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.<br/>\n * Should be used only when you're sure that your <code>iteratee</code> won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * const users = [\n *     {id: 1, name: \"John\"},\n *     {id: 2, name: \"Jane\"},\n *     {id: 3, name: \"Mario\"},\n *     {id: 4, name: \"John\"}\n * ];\n *\n * const 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 <caption>Result of an <code>iteratee</code> producing a duplicate key:</caption>\n * const users = [\n *     {id: 1, name: \"John\"},\n *     {id: 2, name: \"Jane\"},\n *     {id: 3, name: \"Mario\"},\n *     {id: 4, name: \"John\"}\n * ];\n *\n * const 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 * @since 0.21.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} iteratee\n * @returns {Object}\n */\nvar index = _groupWith(function (a, b) {\n    return b;\n});\n\n/**\n * A curried version of {@link module:lamb.index|index} that uses the provided iteratee\n * to build a function expecting the array-like object to act upon.\n * @example\n * const users = [\n *     {id: 1, name: \"John\"},\n *     {id: 2, name: \"Jane\"},\n *     {id: 3, name: \"Mario\"}\n * ];\n * const indexByID = _.indexBy(_.getKey(\"id\"));\n *\n * const 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 * @since 0.21.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nvar indexBy = _curry2(index, true);\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 * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\nvar 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.<br/>\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.<br/>\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 * const 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 * @see {@link module:lamb.append|append}, {@link module:lamb.appendTo|appendTo}\n * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} element\n * @returns {Array}\n */\nfunction insert (arrayLike, index, element) {\n    var result = slice(arrayLike, 0, arrayLike.length);\n\n    result.splice(index, 0, element);\n\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 * const 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 * @function\n * @see {@link module:lamb.insert|insert}\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.append|append}, {@link module:lamb.appendTo|appendTo}\n * @since 0.27.0\n * @param {Number} index\n * @param {*} element\n * @returns {Function}\n */\nvar insertAt = _makePartial3(insert);\n\n/**\n * Returns an array of every unique item that is included in all two given arrays\n * or array-like objects.<br/>\n * Note that this function uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.\n * @example\n * const a1 = [1, 2, 3, 4];\n * const a2 = [2, 5, 4, 2, 6];\n * const a3 = [5, 6, 7];\n *\n * _.intersection(a1, a2) // => [2, 4]\n * _.intersection(a2, a3) // => [5, 6]\n * _.intersection(a1, a3) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.difference|difference}\n * @see {@link module:lamb.symmetricDifference|symmetricDifference}\n * @see {@link module:lamb.union|union}, {@link module:lamb.unionBy|unionBy}\n * @since 0.5.0\n * @param {ArrayLike} a\n * @param {ArrayLike} b\n * @returns {Array}\n */\nfunction intersection (a, b) {\n    var result = [];\n    var resultLookup = new _LookupHelper();\n    var bLookup = new _LookupHelper(b);\n    var lenA = a.length;\n\n    if (lenA && b.length) {\n        for (var i = 0, v; i < lenA; i++) {\n            v = a[i];\n\n            if (!resultLookup.has(v) && bLookup.has(v)) {\n                resultLookup.add(v);\n                result.push(v);\n            }\n        }\n    }\n\n    return result;\n}\n\n/**\n * Transforms an array-like object into a string by joining its elements with\n * the given separator.<br/>\n * Note that unlike the native method, this function won't convert\n * <code>null</code> and <code>undefined</code> values in the array to empty\n * strings and that the <code>separator</code> parameter isn't optional.<br/>\n * See the examples about these differences.\n * @example\n * const words = [\"foo\", \"bar\", \"baz\"];\n *\n * _.join(words, \"-\") // => \"foo-bar-baz\"\n *\n * @example <caption>Showing the differences with the native array method:</caption>\n * const mixed = [1, null, 2, undefined, 3, NaN, 4, 5];\n * const numbers = [1, 2, 3];\n *\n * _.join(mixed, \"-\") // => \"1-null-2-undefined-3-NaN-4-5\"\n * mixed.join(\"-\") // => \"1--2--3-NaN-4-5\"\n *\n * _.join(numbers) // => \"1undefined2undefined3\"\n * numbers.join() // => \"1,2,3\"\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.joinWith|joinWith}\n * @see {@link module:lamb.split|split}, {@link module:lamb.splitBy|splitBy}\n * @since 0.58.0\n * @param {ArrayLike} arrayLike\n * @param {String} separator\n * @returns {String}\n */\nfunction join (arrayLike, separator) {\n    return map(arrayLike, String).join(String(separator));\n}\n\n/**\n * A curried version of {@link module:lamb.join|join} that accepts an optional\n * separator and builds a function expecting the array-like object to act upon.<br/>\n * Please refer to the description and examples of {@link module:lamb.join|join}\n * to understand the differences with the native array method.\n * @example\n * const words = [\"foo\", \"bar\", \"baz\"];\n * const joinWithDash = _.joinWith(\"-\");\n *\n * joinWithDash(words) // => \"foo-bar-baz\"\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.join|join}\n * @see {@link module:lamb.split|split}, {@link module:lamb.splitBy|splitBy}\n * @since 0.58.0\n * @param {String} separator\n * @returns {Function}\n */\nvar joinWith = _curry2(join, true);\n\n/**\n * Retrieves the last element of an array-like object.<br/>\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 * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\nvar last = getAt(-1);\n\n/**\n * Builds helper functions to extract portions of the arguments\n * object rather efficiently without having to write for loops\n * manually for each case.<br/>\n * The arguments object needs to be passed to the apply method\n * of the generated function.\n * @private\n * @param {Number} idx\n * @returns {Function}\n */\nfunction _argsToArrayFrom (idx) {\n    return function () {\n        var argsLen = arguments.length || idx;\n        var len = argsLen - idx;\n        var result = Array(len);\n\n        for (var i = 0; i < len; i++) {\n            result[i] = arguments[i + idx];\n        }\n\n        return result;\n    };\n}\n\n/**\n * Generates an array with the values passed as arguments.<br/>\n * Behaves like ES6's [Array.of]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of}.\n * @example\n * _.list(1, 2, 3) // => [1, 2, 3]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @since 0.1.0\n * @param {...*} value\n * @returns {Array}\n */\nvar list = _argsToArrayFrom(0);\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 * const isEven = n => n % 2 === 0;\n * const 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 * @since 0.11.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {Array<Array, Array>}\n */\nfunction partition (arrayLike, predicate) {\n    var result = [[], []];\n    var len = arrayLike.length;\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 * A curried version of {@link module:lamb.partition|partition} that uses the provided\n * predicate to build a function expecting the array-like object to act upon.\n * @example\n * const 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 * const isActive = _.hasKeyValue(\"active\", true);\n * const 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 * @since 0.11.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar partitionWith = _curry2(partition, true);\n\n/**\n * Returns the value of the object property with the given key.\n * @example\n * const 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 * @since 0.18.0\n * @param {Object} source\n * @param {String} key\n * @returns {*}\n */\nfunction getIn (source, key) {\n    return source[key];\n}\n\n/**\n * A curried version of {@link module:lamb.getIn|getIn}.<br/>\n * Receives a property name and builds a function expecting the object from which we want to retrieve\n * the property.\n * @example\n * const user1 = {name: \"john\"};\n * const user2 = {name: \"jane\"};\n * const getName = _.getKey(\"name\");\n *\n * getName(user1) // => \"john\"\n * getName(user2) // => \"jane\"\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.getIn|getIn}\n * @see {@link module:lamb.getPath|getPath}, {@link module:lamb.getPathIn|getPathIn}\n * @since 0.1.0\n * @param {String} key\n * @returns {Function}\n */\nvar getKey = _curry2(getIn, true);\n\n/**\n * A curried version of {@link module:lamb.pluckFrom|pluckFrom} expecting the key to retrieve to\n * build a function waiting for the array-like object to act upon.\n * @example\n * const 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 * const getAges = _.pluck(\"age\");\n *\n * getAges(persons) // => [12, 40, 18, 15]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.pluckFrom|pluckFrom}\n * @since 0.12.0\n * @param {String} key\n * @returns {Function}\n */\nvar pluck = compose(mapWith, getKey);\n\n/**\n * \"Plucks\" the values of the specified key from a list of objects.\n * @example\n * const 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 * _.pluckFrom(persons, \"age\") // => [12, 40, 18, 15]\n *\n * const lists = [\n *     [1, 2],\n *     [3, 4, 5],\n *     [6]\n * ];\n *\n * _.pluckFrom(lists, \"length\") // => [2, 3, 1]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.pluck|pluck}\n * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @param {String} key\n * @returns {Array}\n */\nfunction pluckFrom (arrayLike, key) {\n    return map(arrayLike, getKey(key));\n}\n\n/**\n * Creates an array copy of the given array-like object without the\n * specified values.<br/>\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.pullFrom(arr, [2, 5]) // => [1, 3, 4]\n *\n * @example <caption>It's not the same as {@link module:lamb.difference|difference}:</caption>\n *\n * const arr = [1,1,2,3,4,4,5];\n *\n * _.pullFrom(arr, [1, 2]) // => [3, 4, 4, 5]\n * _.difference(arr, [1, 2]) // => [3, 4, 5]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.pull|pull}\n * @see {@link module:lamb.difference|difference}\n * @since 0.45.0\n * @param {ArrayLike} arrayLike\n * @param {ArrayLike} values\n * @returns {Array}\n */\nfunction pullFrom (arrayLike, values) {\n    return values ? filter(arrayLike, function (element) {\n        return !isIn(values, element);\n    }) : slice(arrayLike, 0, arrayLike.length);\n}\n\n/**\n * A curried version of {@link module:lamb.pullFrom|pullFrom} expecting\n * a list of values to build a function waiting for an array-like object.<br/>\n * The new function will create an array copy of the array-like without\n * the specified values.<br/>\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.<br/>\n * See examples in {@link module:lamb.pullFrom|pullFrom} about the\n * relationship with {@link module:lamb.difference|difference}.\n * @example\n * const scores = [40, 20, 30, 10];\n * const newScores = [30, 10];\n * const pullNewScores = _.pull(newScores);\n *\n * pullNewScores(scores) // => [40, 20]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.pullFrom|pullFrom}\n * @see {@link module:lamb.difference|difference}\n * @since 0.45.0\n * @param {ArrayLike} values\n * @returns {Function}\n */\nvar pull = _curry2(pullFrom, true);\n\n/**\n * Same as {@link module:lamb.reduce|reduce}, but starts the fold operation from the last\n * element instead.<br/>\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 * @since 0.1.0\n * @param {ArrayLike} arrayLike\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {*}\n */\nvar reduceRight = _makeReducer(-1);\n\n/**\n * A partial application of {@link module:lamb.reduce|reduceRight} that uses the\n * provided <code>accumulator</code> and the optional <code>initialValue</code> to\n * build a function expecting the array-like object to act upon.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.reduceRightWith(_.sum)(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 * @since 0.27.0\n * @param {AccumulatorCallback} accumulator\n * @param {*} [initialValue]\n * @returns {Function}\n */\nvar reduceRightWith = _makePartial3(reduceRight, true);\n\n/**\n * Reverses a copy of the given array-like object.\n * @example\n * const 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 * @since 0.19.0\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\nfunction reverse (arrayLike) {\n    var len = _toArrayLength(arrayLike.length);\n    var result = Array(len);\n\n    for (var i = 0, ofs = len - 1; i < len; i++) {\n        result[i] = arrayLike[ofs - i];\n    }\n\n    return result;\n}\n\n/**\n * Returns a copy of the given array-like with the element rotated by the desired amount.\n * Negative indexes are allowed.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.rotate(arr, 3) // => [3, 4, 5, 1, 2]\n * _.rotate(arr, -3) // => [4, 5, 1, 2, 3]\n * _.rotate(arr, 11) // => [5, 1, 2, 3, 4]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.rotateBy|rotateBy}\n * @since 0.55.0\n * @param {ArrayLike} arrayLike\n * @param {Number} amount\n * @returns {Array}\n */\nfunction rotate (arrayLike, amount) {\n    var len = arrayLike.length;\n    var shift = amount % len;\n\n    return slice(arrayLike, -shift, len).concat(slice(arrayLike, 0, -shift));\n}\n\n/**\n * A curried version of {@link module:lamb.rotate|rotate}.<br/>\n * Uses the given amount to build a function expecting the array to rotate by that amount.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n * const rotateByTwo = _.rotateBy(2);\n *\n * rotateByTwo(arr) // => [4, 5, 1, 2, 3]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.rotate|rotate}\n * @since 0.55.0\n * @param {Number} amount\n * @returns {Function}\n */\nvar rotateBy = _curry2(rotate, true);\n\n/**\n * Sets an index in an array-like object.<br/>\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} idx\n * @param {*} [value]\n * @param {Function} [updater]\n * @returns {Array}\n */\nfunction _setIndex (arrayLike, idx, value, updater) {\n    var result = slice(arrayLike, 0, arrayLike.length);\n    var n = _toNaturalIndex(idx, result.length);\n\n    if (n === n) { // eslint-disable-line no-self-compare\n        result[n] = arguments.length === 4 ? updater(arrayLike[n]) : value;\n    }\n\n    return result;\n}\n\n/**\n * A curried version of {@link module:lamb.setIndex|setIndex} that builds\n * a function that creates a copy of an array-like object with the given\n * index changed to the desired value.<br/>\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.<br/>\n * Negative indexes are allowed.\n * @example\n * const 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 <caption>Using negative indexes:</caption>\n * _.setAt(-1, 99)(arr) // => [1, 2, 3, 4, 99]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.setIndex|setIndex}\n * @since 0.17.0\n * @param {Number} index\n * @param {*} value\n * @returns {Function}\n */\nvar setAt = _makePartial3(_setIndex);\n\n/**\n * Builds a new function that passes only the specified amount of arguments to the original one.<br/>\n * As {@link module:lamb.slice|slice} is used to extract the arguments, you can also\n * pass a negative arity.\n * @example\n * Math.max(10, 11, 45, 99) // => 99\n * _.aritize(Math.max, 2)(10, 11, 45, 99) // => 11\n *\n * @example <caption>Using a negative arity:</caption>\n * _.aritize(Math.max, -1)(10, 11, 45, 99) // => 45\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.binary|binary}, {@link module:lamb.unary|unary} for common use cases shortcuts\n * @since 0.1.0\n * @param {Function} fn\n * @param {Number} arity\n * @returns {Function}\n */\nfunction aritize (fn, arity) {\n    return function () {\n        var n = _toInteger(arity);\n        var args = list.apply(null, arguments).slice(0, n);\n\n        for (var i = args.length; i < n; i++) {\n            args[i] = void 0;\n        }\n\n        return fn.apply(this, args);\n    };\n}\n\n/**\n * Creates a copy of an array-like object with the given index changed to\n * the desired value.<br/>\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.<br/>\n * Negative indexes are allowed.\n * @example\n * const 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 * @since 0.23.0\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {*} value\n * @returns {Array}\n */\nvar setIndex = aritize(_setIndex, 3);\n\n/**\n * Flattens the \"first level\" of an array.\n * @example <caption>Showing the difference with <code>flatten</code>:</caption>\n * const 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 * @function\n * @see {@link module:lamb.flatten|flatten}\n * @since 0.9.0\n * @param {Array} array\n * @returns {Array}\n */\nvar shallowFlatten = _makeArrayFlattener(false);\n\n/**\n * Checks if at least one element in an array-like object satisfies the given predicate.<br/>\n * The function will stop calling the predicate as soon as it returns a <em>truthy</em> value.<br/>\n * Note that unlike the native\n * [Array.prototype.some]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some},\n * this function won't skip deleted or unassigned indexes.\n * @example\n * const persons = [\n *     {\"name\": \"Jane\", \"age\": 12, active: false},\n *     {\"name\": \"John\", \"age\": 40, active: false},\n *     {\"name\": \"Mario\", \"age\": 17, active: false},\n *     {\"name\": \"Paolo\", \"age\": 15, active: false}\n * ];\n * const isAdult = _.keySatisfies(_.isGTE(18), \"age\");\n * const isActive = _.hasKeyValue(\"active\", true);\n *\n * _.someIn(persons, isAdult) // => true\n * _.someIn(persons, isActive) // => false\n *\n * @example <caption>Showing the difference with <code>Array.prototype.some</code>:</caption>\n * const arr = new Array(5);\n * arr[3] = 99;\n *\n * arr.some(_.isUndefined) // => false\n * _.someIn(arr, _.isUndefined) // => true\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.some|some}\n * @see {@link module:lamb.every|every}, {@link module:lamb.everyIn|everyIn}\n * @since 0.39.0\n * @param {ArrayLike} arrayLike\n * @param {ListIteratorCallback} predicate\n * @returns {Boolean}\n */\nvar someIn = _makeArrayChecker(false);\n\n/**\n * A curried version of {@link module:lamb.someIn|someIn} that uses the given predicate to\n * build a function waiting for the array-like to act upon.\n * @example\n * const data = [1, 3, 5, 6, 7, 8];\n * const isEven = n => n % 2 === 0;\n * const containsEvens = _.some(isEven);\n * const containsStrings = _.some(_.isType(\"String\"));\n *\n * containsEvens(data) // => true\n * containsStrings(data) // => false\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.someIn|someIn}\n * @see {@link module:lamb.every|every}, {@link module:lamb.everyIn|everyIn}\n * @since 0.39.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar some = _curry2(someIn, true);\n\n/**\n * Accepts a list of sorting criteria with at least one element\n * and builds a function that compares two values with such criteria.\n * @private\n * @param {Sorter[]} criteria\n * @returns {Function}\n */\nfunction _compareWith (criteria) {\n    return function (a, b) {\n        var len = criteria.length;\n        var criterion = criteria[0];\n        var result = criterion.compare(a.value, b.value);\n\n        for (var i = 1; result === 0 && i < len; i++) {\n            criterion = criteria[i];\n            result = criterion.compare(a.value, b.value);\n        }\n\n        if (result === 0) {\n            result = a.index - b.index;\n        }\n\n        return criterion.isDescending ? -result : result;\n    };\n}\n\n/**\n * The default comparer for sorting functions.<br/>\n * If the given values are of different types they\n * will be both converted to strings.<br/>\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\nfunction _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 (!areSVZ(a, b)) {\n        // eslint-disable-next-line no-self-compare\n        result = a > b || a !== a ? 1 : -1;\n    }\n\n    return result;\n}\n\n/**\n * Builds a sorting criterion. If the comparer function is missing, the default\n * comparer will be used instead.\n * @private\n * @param {Function} reader\n * @param {Boolean} isDescending\n * @param {Function} [comparer]\n * @returns {Sorter}\n */\nfunction _sorter (reader, isDescending, comparer) {\n    if (typeof reader !== \"function\" || reader === identity) {\n        reader = null;\n    }\n\n    if (typeof comparer !== \"function\") {\n        comparer = _comparer;\n    }\n\n    return {\n        isDescending: isDescending === true,\n        compare: function (a, b) {\n            if (reader) {\n                a = reader(a);\n                b = reader(b);\n            }\n\n            return comparer(a, b);\n        }\n    };\n}\n\n/**\n * Converts a sorting function to a sorting criterion if necessary.\n * @private\n * @param {Function} criterion\n * @returns {Sorter}\n */\nfunction _makeCriterion (criterion) {\n    return criterion && typeof criterion.compare === \"function\" ? criterion : _sorter(criterion);\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 */\nfunction _makeCriteria (sorters) {\n    return sorters && sorters.length ? map(sorters, _makeCriterion) : [_sorter()];\n}\n\n/**\n * Returns a [stably]{@link https://en.wikipedia.org/wiki/Sorting_algorithm#Stability} sorted\n * copy of an array-like object using the given criteria.<br/>\n * Sorting criteria are built using Lamb's {@link module:lamb.sorter|sorter} function, but you\n * can also pass simple \"reader\" functions and default ascending sorters will be built for you.<br/>\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used\n * in the comparison.<br/>\n * Please note that if the arguments received by the default comparer aren't of the same type,\n * they will be compared as strings.\n *\n * @example <caption>Stable sort:</caption>\n * const persons = [\n *     {\"name\": \"John\", \"surname\" :\"Doe\"},\n *     {\"name\": \"Mario\", \"surname\": \"Rossi\"},\n *     {\"name\": \"John\", \"surname\" :\"Moe\"},\n *     {\"name\": \"Jane\", \"surname\": \"Foe\"}\n * ];\n *\n * const 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 <caption>Stable multi-sort:</caption>\n * const personsByNameAscSurnameDesc = _.sort(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 <caption>Using custom comparers:</caption>\n * const localeSorter = new Intl.Collator(\"it\");\n * const chars = [\"a\", \"è\", \"à\", \"é\", \"c\", \"b\", \"e\"];\n *\n * _.sort(chars, [localeSorter]) // => [\"a\", \"à\", \"b\", \"c\", \"e\", \"é\", \"è\"]\n *\n * const 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 * @since 0.15.0\n * @param {ArrayLike} arrayLike\n * @param {Sorter[]|Function[]} [sorters=[{@link module:lamb.sorter|sorter()}]]\n * @returns {Array}\n */\nfunction sort (arrayLike, sorters) {\n    var criteria = _makeCriteria(sorters);\n    var len = _toArrayLength(arrayLike.length);\n    var result = Array(len);\n\n    for (var i = 0; i < len; i++) {\n        result[i] = { value: arrayLike[i], index: i };\n    }\n\n    result.sort(_compareWith(criteria));\n\n    for (i = 0; i < len; i++) {\n        result[i] = result[i].value;\n    }\n\n    return result;\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 * @private\n * @param {Array} array\n * @param {*} element\n * @param {Function} comparer\n * @param {Number} start\n * @param {Number} end\n * @returns {Number}\n */\nfunction _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, index: pivot },\n        { value: array[pivot], 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 * Inserts an element in a copy of a sorted array respecting the sort order.\n * @example <caption>With simple values:</caption>\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 <caption>With complex values:</caption>\n * const persons = [\n *     {\"name\": \"jane\", \"surname\": \"doe\"},\n *     {\"name\": \"John\", \"surname\": \"Doe\"},\n *     {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * ];\n *\n * const getLowerCaseName = _.compose(\n *     _.invoke(\"toLowerCase\"),\n *     _.getKey(\"name\")\n * );\n *\n * const 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\n * at a specific index\n * @since 0.27.0\n * @param {ArrayLike} arrayLike\n * @param {*} element\n * @param {Sorter[]|Function[]} [sorters=[{@link module:lamb.sorter|sorter()}]] - The sorting criteria\n * used to sort the array.\n * @returns {Array}\n */\nfunction sortedInsert (arrayLike, element, sorters) {\n    var result = slice(arrayLike, 0, arrayLike.length);\n\n    if (arguments.length === 1) {\n        return result;\n    }\n\n    var criteria = _makeCriteria(sorters);\n    var idx = _getInsertionIndex(result, element, _compareWith(criteria), 0, result.length);\n\n    result.splice(idx, 0, element);\n\n    return result;\n}\n\n/**\n * Creates an ascending sort criterion with the provided <code>reader</code> and\n * <code>comparer</code>.<br/>\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 * @since 0.1.0\n * @param {Function} [reader={@link module:lamb.identity|identity}] A function meant to generate a\n * simple value from a complex one. The function should evaluate the array element and supply the\n * value to be passed to the comparer.\n * @param {Function} [comparer] An optional custom comparer function.\n * @returns {Sorter}\n */\nvar sorter = partial(_sorter, [__, false, __]);\n\n/**\n * Creates a descending sort criterion with the provided <code>reader</code> and\n * <code>comparer</code>.<br/>\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 * @since 0.15.0\n * @param {Function} [reader={@link module:lamb.identity|identity}] A function meant to generate a\n * simple value from a complex one. The function should evaluate the array element and supply the\n * value to be passed to the comparer.\n * @param {Function} [comparer] An optional custom comparer function.\n * @returns {Sorter}\n */\nvar sorterDesc = partial(_sorter, [__, true, __]);\n\n/**\n * Builds a partial application of {@link module:lamb.sort|sort} using the provided criteria.\n * The returned function expects the array-like object to sort.\n * As usual, sorting criteria are built using Lamb's {@link module:lamb.sorter|sorter} function,\n * but you can also pass simple \"reader\" functions and default ascending sorters will be built.<br/>\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in\n * the comparison.<br/>\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 * @function\n * @see {@link module:lamb.sort|sort}\n * @see {@link module:lamb.sorter|sorter}, {@link module:lamb.sorterDesc|sorterDesc}\n * @since 0.15.0\n * @param {Sorter[]|Function[]} [sorters=[{@link module:lamb.sorter|sorter()}]]\n * @returns {Function}\n */\nvar sortWith = _curry2(sort, true);\n\n/**\n * Returns the [symmetric difference]{@link https://en.wikipedia.org/wiki/Symmetric_difference}\n * of two array-like objects. In other words returns the array of unique\n * items contained in the first or second array-like, but not the ones\n * in their {@link module:lamb.intersection|intersection}.<br/>\n * To determine uniqueness the function uses the\n * [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.\n * @example\n * const a1 = [0, 1, 2, 3, 2, 4, NaN];\n * const a2 = [-0, 2, 3, 4, 5, NaN];\n * const a3 = [1, 3, 4, 5];\n *\n * _.symmetricDifference(a1, a2) // => [1, 5]\n * _.symmetricDifference(a2, a3) // => [-0, 2, NaN, 1]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.difference|difference}\n * @see {@link module:lamb.intersection|intersection}\n * @see {@link module:lamb.union|union}, {@link module:lamb.unionBy|unionBy}\n * @since 0.61.0\n * @param {ArrayLike} a\n * @param {ArrayLike} b\n * @returns {Array}\n */\nfunction symmetricDifference (a, b) {\n    return difference(a, b).concat(difference(b, a));\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 * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {Array}\n */\nvar tail = drop(1);\n\n/**\n * Retrieves the first <code>n</code> elements from an array or array-like object.<br/>\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * <code>n</code> can be a negative number.\n * @example\n * const arr = [1, 2, 3, 4, 5];\n *\n * _.takeFrom(arr, 3) // => [1, 2, 3]\n * _.takeFrom(arr, -1) // => [1, 2, 3, 4]\n * _.takeFrom(arr, -10) // => []\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.take|take}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropLastWhile|dropLastWhile}\n * @since 0.51.0\n * @param {ArrayLike} arrayLike\n * @param {Number} n\n * @returns {Array}\n */\nfunction takeFrom (arrayLike, n) {\n    return slice(arrayLike, 0, n);\n}\n\n/**\n * A curried version of {@link module:lamb.takeFrom|takeFrom} that expects the number of elements\n * to retrieve to build a function waiting for the list to take the elements from.<br/>\n * See the note and examples for {@link module:lamb.takeFrom|takeFrom} about passing a\n * negative <code>n</code>.\n * @example\n * const take2 = _.take(2);\n *\n * take2([1, 2, 3, 4, 5]) // => [1, 2]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.takeFrom|takeFrom}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropLastWhile|dropLastWhile}\n * @since 0.5.0\n * @param {Number} n\n * @returns {Function}\n */\nvar take = _curry2(takeFrom, true);\n\n/**\n * Builds a function that takes the last elements satisfying a predicate\n * from an array or array-like object.\n * @example\n * const isEven = n => n % 2 === 0;\n * const takeLastWhileIsEven = _.takeLastWhile(isEven);\n *\n * takeLastWhileIsEven([1, 3, 5, 7]) // => []\n * takeLastWhileIsEven([2, 3, 6, 8]) // => [6, 8]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.dropLastWhile|dropLastWhile}\n * @see {@link module:lamb.takeWhile|takeWhile}, {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @see {@link module:lamb.takeFrom|takeFrom}, {@link module:lamb.take|take}\n * @since 0.58.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar takeLastWhile = _takeOrDropWhile(true, true);\n\n/**\n * Builds a function that takes the first elements satisfying a predicate from\n * an array or array-like object.\n * @example\n * const isEven = n => n % 2 === 0;\n * const 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 * @function\n * @see {@link module:lamb.dropWhile|dropWhile}\n * @see {@link module:lamb.takeLastWhile|takeLastWhile}, {@link module:lamb.dropLastWhile|dropLastWhile}\n * @see {@link module:lamb.takeFrom|takeFrom}, {@link module:lamb.take|take}\n * @see {@link module:lamb.dropFrom|dropFrom}, {@link module:lamb.drop|drop}\n * @since 0.5.0\n * @param {ListIteratorCallback} predicate\n * @returns {Function}\n */\nvar takeWhile = _takeOrDropWhile(true, false);\n\n/**\n * Transposes a matrix. Can also be used to reverse a {@link module:lamb.zip|zip} operation.<br/>\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example <caption>Transposing a matrix:</caption>\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 <caption>Showing the relationship with <code>zip</code>:</caption>\n * const 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 * @see {@link module:lamb.zip|zip}\n * @since 0.14.0\n * @param {ArrayLike<ArrayLike>} arrayLike\n * @returns {Array<Array>}\n */\nfunction transpose (arrayLike) {\n    var minLen = MAX_ARRAY_LENGTH;\n    var len = _toArrayLength(arrayLike.length);\n\n    if (len === 0) {\n        return [];\n    }\n\n    for (var j = 0, elementLen; j < len; j++) {\n        elementLen = _toArrayLength(arrayLike[j].length);\n\n        if (elementLen < minLen) {\n            minLen = elementLen;\n        }\n    }\n\n    var result = Array(minLen);\n\n    for (var i = 0, el; i < minLen; i++) {\n        el = result[i] = Array(len);\n\n        for (j = 0; j < len; j++) {\n            el[j] = arrayLike[j][i];\n        }\n    }\n\n    return result;\n}\n\n/**\n * Creates a pipeline of functions, where each function consumes the result of the previous one.\n * @example\n * const square = n => n ** 2;\n * const getMaxAndSquare = _.pipe([Math.max, square]);\n *\n * getMaxAndSquare(3, 5) // => 25\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @see {@link module:lamb.compose|compose}\n * @since 0.1.0\n * @param {Function[]} functions\n * @returns {Function}\n */\nfunction pipe (functions) {\n    if (!Array.isArray(functions)) {\n        throw _makeTypeErrorFor(functions, \"array\");\n    }\n\n    var len = functions.length;\n\n    return len ? function () {\n        var result = functions[0].apply(this, arguments);\n\n        for (var i = 1; i < len; i++) {\n            result = functions[i].call(this, result);\n        }\n\n        return result;\n    } : identity;\n}\n\n/**\n * Using the provided iteratee to transform values, builds a function that will\n * return an array of the unique elements  in the two provided array-like objects.<br/>\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.<br/>\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.<br/>\n * See also {@link module:lamb.union|union} if you don't need to compare transformed values.\n * @example\n * const unionByFloor = _.unionBy(Math.floor);\n *\n * unionByFloor([2.8, 3.2, 1.5], [3.5, 1.2, 4]) // => [2.8, 3.2, 1.5, 4]\n *\n * @memberof module:lamb\n * @category Array\n * @see {@link module:lamb.union|union}\n * @see {@link module:lamb.difference|difference}\n * @see {@link module:lamb.intersection|intersection}\n * @see {@link module:lamb.symmetricDifference|symmetricDifference}\n * @since 0.51.0\n * @param {ListIteratorCallback} iteratee\n * @returns {Function}\n */\nfunction unionBy (iteratee) {\n    return pipe([binary(list), flatMapWith(drop(0)), uniquesBy(iteratee)]);\n}\n\n/**\n * Returns a list of every unique element present in the two given array-like objects.<br/>\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.<br/>\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.<br/>\n * See also {@link module:lamb.unionBy|unionBy} if you need to transform the values before\n * the comparison or if you have to extract them from complex ones.\n * @example\n * _.union([1, 2, 3, 2], [2, 3, 4]) // => [1, 2, 3, 4]\n * _.union(\"abc\", \"bcd\") // => [\"a\", \"b\", \"c\", \"d\"]\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.unionBy|unionBy}\n * @see {@link module:lamb.difference|difference}\n * @see {@link module:lamb.intersection|intersection}\n * @see {@link module:lamb.symmetricDifference|symmetricDifference}\n * @since 0.5.0\n * @param {ArrayLike} a\n * @param {ArrayLike} b\n * @returns {Array}\n */\nvar union = unionBy(identity);\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.<br/>\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.<br/>\n * Negative indexes are allowed.\n * @example\n * const arr = [\"a\", \"b\", \"c\"];\n * const toUpperCase = _.invoke(\"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 * @since 0.22.0\n * @param {Number} index\n * @param {Function} updater\n * @returns {Function}\n */\nfunction updateAt (index, updater) {\n    return function (arrayLike) {\n        return _setIndex(arrayLike, index, null, updater);\n    };\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.<br/>\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.<br/>\n * Negative indexes are allowed.\n * @example\n * const arr = [\"a\", \"b\", \"c\"];\n * const toUpperCase = _.invoke(\"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 * @since 0.23.0\n * @param {ArrayLike} arrayLike\n * @param {Number} index\n * @param {Function} updater\n * @returns {Array}\n */\nvar updateIndex = partial(_setIndex, [__, __, null, __]);\n\n/**\n * Builds a list of arrays out of the two given array-like objects by pairing items with\n * the same index.<br/>\n * The received array-like objects will be truncated to the shortest length.\n * @example\n * _.zip(\n *     [\"a\", \"b\", \"c\"],\n *     [1, 2, 3]\n * ) // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\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 * @see {@link module:lamb.transpose|transpose} for the reverse operation\n * @see {@link module:lamb.zipWithIndex|zipWithIndex}\n * @since 0.14.0\n * @param {ArrayLike} a\n * @param {ArrayLike} b\n * @returns {Array<Array>}\n */\nfunction zip (a, b) {\n    return transpose([a, b]);\n}\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 * @see {@link module:lamb.zip|zip}\n * @since 0.14.0\n * @param {ArrayLike} arrayLike\n * @returns {Array<Array<*, Number>>}\n */\nvar zipWithIndex = mapWith(binary(list));\n\n/**\n * Applies the given function to a list of arguments.\n * @example\n * _.application(_.sum, [3, 4]) // => 7\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.apply|apply}, {@link module:lamb.applyTo|applyTo}\n * @since 0.47.0\n * @param {Function} fn\n * @param {ArrayLike} args\n * @returns {*}\n */\nfunction application (fn, args) {\n    return fn.apply(this, Object(args));\n}\n\n/**\n * A left-curried version of {@link module:lamb.application|application}. Expects the function\n * to apply and builds a function waiting for the arguments array.\n * @example\n * const arrayMax = _.apply(Math.max);\n *\n * arrayMax([4, 5, 2, 6, 1]) // => 6\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @see {@link module:lamb.application|application}, {@link module:lamb.applyTo|applyTo}\n * @since 0.1.0\n * @param {Function} fn\n * @returns {Function}\n */\nvar apply = _curry2(application);\n\n/**\n * A right-curried version of {@link module:lamb.application|application}. Expects an array-like\n * object to use as arguments and builds a function waiting for the target of the application.\n * @example\n * const data = [3, 4];\n * const applyToData = _.applyTo(data);\n *\n * applyToData(_.sum) // => 7\n * applyToData(_.multiply) // => 12\n *\n * @memberof module:lamb\n * @category Function\n * @function\n * @see {@link module:lamb.application|application}, {@link module:lamb.apply|apply}\n * @since 0.47.0\n * @param {ArrayLike} args\n * @returns {Function}\n */\nvar applyTo = _curry2(application, true);\n\n/**\n * Keeps building a partial application of the received function as long\n * as it's called with placeholders; applies the original function to\n * the collected parameters otherwise.<br/>\n * The function checks only the public placeholder to gain a little performance\n * as no function in Lamb is built with {@link module:lamb.asPartial|asPartial}.\n * @private\n * @param {Function} fn\n * @param {Array} argsHolder\n * @returns {Function|*}\n */\nfunction _asPartial (fn, argsHolder) {\n    return function () {\n        var argsLen = arguments.length;\n        var lastIdx = 0;\n        var newArgs = [];\n\n        for (var i = 0, len = argsHolder.length, boundArg; i < len; i++) {\n            boundArg = argsHolder[i];\n            newArgs[i] = boundArg === __ && lastIdx < argsLen ? arguments[lastIdx++] : boundArg;\n        }\n\n        while (lastIdx < argsLen) {\n            newArgs[i++] = arguments[lastIdx++];\n        }\n\n        for (i = 0; i < argsLen; i++) {\n            if (arguments[i] === __) {\n                return _asPartial(fn, newArgs);\n            }\n        }\n\n        for (i = 0, len = newArgs.length; i < len; i++) {\n            if (newArgs[i] === __) {\n                newArgs[i] = void 0;\n            }\n        }\n\n        return fn.apply(this, newArgs);\n    };\n}\n\n/**\n * Decorates the received function so that it can be called with\n * placeholders to build a partial application of it.<br/>\n * The difference with {@link module:lamb.partial|partial} is that, as long as\n * you call the generated function with placeholders, another partial application\n * of the original function will be built.<br/>\n * The final application will happen when one of the generated functions is\n * invoked without placeholders, using the parameters collected so far. <br/>\n * This function comes in handy when you need to build different specialized\n * functions starting from a basic one, but it's also useful when dealing with\n * optional parameters as you can decide to apply the function even if its arity\n * hasn't been entirely consumed.\n * @example <caption>Explaining the function's behaviour:</caption>\n * const __ = _.__;\n * const f = _.asPartial((a, b, c) => a + b + c);\n *\n * f(4, 3, 2) // => 9\n * f(4, __, 2)(3) // => 9\n * f(__, 3, __)(4, __)(2) // => 9\n *\n * @example <caption>Exploiting optional parameters:</caption>\n * const __ = _.__;\n * const f = _.asPartial((a, b, c) => a + b + (c || 0));\n *\n * const addFive = f(5, __);\n * addFive(2) // => 7\n *\n * const addNine = addFive(4, __);\n * addNine(11) // => 20\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.partial|partial}, {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight}\n * @see {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * @see {@link module:lamb.__|__} The placeholder object.\n * @since 0.36.0\n * @param {Function} fn\n * @returns {Function}\n */\nfunction asPartial (fn) {\n    return _asPartial(fn, []);\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 * <code>collect</code>.<br/>\n * The collected results will be returned in an array.\n * @example\n * const user = {\n *     id: \"jdoe\",\n *     name: \"John\",\n *     surname: \"Doe\",\n *     scores: [2, 4, 7]\n * };\n * const getIDAndLastScore = _.collect([_.getKey(\"id\"), _.getPath(\"scores.-1\")]);\n *\n * getIDAndLastScore(user) // => [\"jdoe\", 7]\n *\n * @example\n * const 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 * @since 0.35.0\n * @param {Function[]} functions\n * @returns {Function}\n */\nfunction collect (functions) {\n    if (!Array.isArray(functions)) {\n        throw _makeTypeErrorFor(functions, \"array\");\n    }\n\n    return function () {\n        return map(functions, applyTo(arguments));\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 {Boolean} isAutoCurry\n * @param {Array} argsHolder\n * @returns {Function}\n */\nfunction _currier (fn, arity, isRightCurry, isAutoCurry, argsHolder) {\n    return function () {\n        var holderLen = argsHolder.length;\n        var argsLen = arguments.length;\n        var newArgsLen = holderLen + (argsLen > 1 && isAutoCurry ? argsLen : 1);\n        var newArgs = Array(newArgsLen);\n\n        for (var i = 0; i < holderLen; i++) {\n            newArgs[i] = argsHolder[i];\n        }\n\n        for (; i < newArgsLen; i++) {\n            newArgs[i] = arguments[i - holderLen];\n        }\n\n        if (newArgsLen >= arity) {\n            return fn.apply(this, isRightCurry ? newArgs.reverse() : newArgs);\n        } else {\n            return _currier(fn, arity, isRightCurry, isAutoCurry, newArgs);\n        }\n    };\n}\n\n/**\n * Curries a function of arity 3.\n * @private\n * @param {Function} fn\n * @param {Boolean} [isRightCurry=false]\n * @returns {Function}\n */\nfunction _curry3 (fn, isRightCurry) {\n    return function (a) {\n        return function (b) {\n            return function (c) {\n                return isRightCurry ? fn.call(this, c, b, a) : fn.call(this, a, b, c);\n            };\n        };\n    };\n}\n\n/**\n * Prepares a function for currying. If it's not auto-currying and the arity\n * is 2 or 3 returns optimized functions, otherwise delegates the currying\n * to the <code>_currier</code> function.<br/>\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=false]\n * @param {Boolean} [isAutoCurry=false]\n * @returns {Function}\n */\nfunction _curry (fn, arity, isRightCurry, isAutoCurry) {\n    if (arity >>> 0 !== arity) {\n        arity = fn.length;\n    }\n\n    if (isAutoCurry && arity > 1 || arity > 3) {\n        return _currier(fn, arity, isRightCurry, isAutoCurry, []);\n    } else if (arity === 2) {\n        return _curry2(fn, isRightCurry);\n    } else if (arity === 3) {\n        return _curry3(fn, isRightCurry);\n    } else {\n        return fn;\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.<br/>\n * Currying will start from the leftmost argument: use {@link module:lamb.curryRight|curryRight}\n * for right currying.\n * @example\n * const makeWithKeys = _.curry(_.make);\n * const makePerson = makeWithKeys([\"name\", \"surname\"]);\n *\n * makePerson([\"John\", \"Doe\"]) // => {name: \"John\", surname: \"Doe\"};\n * makePerson([\"Mario\", \"Rossi\"]) // => {name: \"Mario\", surname: \"Rossi\"};\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.curryRight|curryRight}\n * @see {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * @see {@link module:lamb.partial|partial}, {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.asPartial|asPartial}\n * @since 0.1.0\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\nfunction 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.<br/>\n * Currying will start from the leftmost argument: use {@link module:lamb.curryableRight|curryableRight}\n * for right currying.\n * @example\n * const 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 * @see {@link module:lamb.curryableRight|curryableRight}\n * @see {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight}\n * @see {@link module:lamb.partial|partial}, {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.asPartial|asPartial}\n * @since 0.6.0\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\nfunction 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 * const 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 * @see {@link module:lamb.curryable|curryable}\n * @see {@link module:lamb.curry|curry}, {@link module:lamb.curryRight|curryRight}\n * @see {@link module:lamb.partial|partial}, {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.asPartial|asPartial}\n * @since 0.9.0\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\nfunction 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 * const makeWithValues = _.curryRight(_.make);\n * const makeJohnDoe = makeWithValues([\"John\", \"Doe\"]);\n *\n * makeJohnDoe([\"name\", \"surname\"]) // => {name: \"John\", surname: \"Doe\"};\n * makeJohnDoe([\"firstName\", \"lastName\"]) // => {firstName: \"John\", lastName: \"Doe\"};\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.curry|curry}\n * @see {@link module:lamb.curryable|curryable}, {@link module:lamb.curryableRight|curryableRight}\n * @see {@link module:lamb.partial|partial}, {@link module:lamb.partialRight|partialRight}\n * @see {@link module:lamb.asPartial|asPartial}\n * @since 0.9.0\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @returns {Function}\n */\nfunction 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\n * specified timespan.<br/>\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call\n * happens immediately.\n * @example <caption>A common use case of <code>debounce</code> in a browser environment:</caption>\n * function updateLayout () {\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 * @see {@link module:lamb.throttle|throttle}\n * @since 0.1.0\n * @param {Function} fn\n * @param {Number} timespan - Expressed in milliseconds\n * @returns {Function}\n */\nfunction debounce (fn, timespan) {\n    var timeoutID;\n\n    return function () {\n        var args = arguments;\n        var debounced = function () {\n            timeoutID = null;\n            fn.apply(this, args);\n        }.bind(this);\n\n        clearTimeout(timeoutID);\n        timeoutID = setTimeout(debounced, timespan);\n    };\n}\n\n/**\n * Returns a function that applies the original function with the arguments 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 * @since 0.1.0\n * @param {Function} fn\n * @returns {Function}\n */\nfunction flip (fn) {\n    return function () {\n        var args = list.apply(null, arguments).reverse();\n\n        return fn.apply(this, args);\n    };\n}\n\n/**\n * Builds a function that returns the argument received at the given index.<br/>\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.<br/>\n * The resulting function will return <code>undefined</code> if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * const getFirstArg = _.getArgAt(0);\n * const 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 * @since 0.17.0\n * @param {Number} idx\n * @returns {Function}\n */\nfunction getArgAt (idx) {\n    return function () {\n        return arguments[_toNaturalIndex(idx, arguments.length)];\n    };\n}\n\n/* eslint-disable jsdoc/check-param-names */\n\n/**\n * If a method with the given name exists on the target, applies it to the provided\n * arguments and returns the result. Returns <code>undefined</code> otherwise.<br/>\n * The arguments for the method are built by concatenating the array of bound arguments,\n * received by {@link module:lamb.invoke|invoke}, with the final set of <code>args</code>,\n * if present.\n * @private\n * @param {String} methodName\n * @param {Array} boundArgs\n * @param {Object} target\n * @param {...*} [args]\n * @returns {*}\n */\nfunction _invoke (methodName, boundArgs, target) {\n    var method = target[methodName];\n\n    if (typeof method !== \"function\") {\n        return void 0;\n    }\n\n    var boundArgsLen = boundArgs ? _toArrayLength(boundArgs.length) : 0;\n    var finalArgsLen = boundArgsLen + arguments.length - 3;\n    var finalArgs = Array(finalArgsLen);\n\n    for (var i = 0; i < boundArgsLen; i++) {\n        finalArgs[i] = boundArgs[i];\n    }\n\n    for (var ofs = 3 - i; i < finalArgsLen; i++) {\n        finalArgs[i] = arguments[i + ofs];\n    }\n\n    return method.apply(target, finalArgs);\n}\n\n/**\n * Builds a function that will invoke the given method name on any received object and\n * return the result. If no method with such name is found the function will return\n * <code>undefined</code>.<br/>\n * Along with the method name it's possible to supply some arguments that will be bound to the\n * method call. Further arguments can also be passed when the function is actually called, and\n * they will be concatenated to the bound ones.<br/>\n * Returning <code>undefined</code> is a behaviour meant to quickly create a case for\n * {@link module:lamb.adapter|adapter} without the need to check for the existence of the\n * desired method.<br/>\n * See also {@link module:lamb.generic|generic} to create functions out of object methods.\n * @example <caption>Basic polymorphism with <code>invoke</code>:</caption>\n * const polySlice = _.invoke(\"slice\");\n *\n * polySlice([1, 2, 3, 4, 5], 1, 3) // => [2, 3]\n * polySlice(\"Hello world\", 1, 3) // => \"el\"\n *\n * @example <caption>With bound arguments:</caption>\n * const substringFrom2 = _.invoke(\"substring\", [2]);\n *\n * substringFrom2(\"Hello world\") // => \"llo world\"\n * substringFrom2(\"Hello world\", 5) // => \"llo\"\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.invokeOn|invokeOn}\n * @since 0.1.0\n * @param {String} methodName\n * @param {ArrayLike} [boundArgs=[]]\n * @returns {Function}\n */\nfunction invoke (methodName, boundArgs) {\n    return partial(_invoke, [methodName, boundArgs]);\n}\n\n/**\n * Accepts an object and builds a function expecting a method name, and optionally arguments,\n * to call on such object.\n * Like {@link module:lamb.invoke|invoke}, if no method with the given name is found the\n * function will return <code>undefined</code>.\n * @example\n * const isEven = n => n % 2 === 0;\n * const arr = [1, 2, 3, 4, 5];\n * const invokeOnArr = _.invokeOn(arr);\n *\n * invokeOnArr(\"filter\", isEven) // => [2, 4]\n * invokeOnArr(\"slice\", 1, 3) // => [2, 3]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.invoke|invoke}\n * @since 0.15.0\n * @param {Object} target\n * @returns {Function}\n */\nfunction invokeOn (target) {\n    return partial(_invoke, [__, [], target]);\n}\n\n/**\n * Builds a function that allows to map over the received arguments before applying them\n * to the original one.\n * @example\n * const sumArray = _.reduceWith(_.sum);\n * const sumArgs = _.compose(sumArray, _.list);\n *\n * sumArgs(1, 2, 3, 4, 5) // => 15\n *\n * const square = n => n ** 2;\n * const sumSquares = _.mapArgs(sumArgs, square);\n *\n * sumSquares(1, 2, 3, 4, 5) // => 55\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.tapArgs|tapArgs}\n * @since 0.3.0\n * @param {Function} fn\n * @param {ListIteratorCallback} mapper\n * @returns {Function}\n */\nfunction mapArgs (fn, mapper) {\n    return pipe([list, mapWith(mapper), apply(fn)]);\n}\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 * const someObject = {count: 5};\n * const someArrayData = [2, 3, 123, 5, 6, 7, 54, 65, 76, 0];\n * const getDataAmount = _.tapArgs(_.sum, [_.getKey(\"count\"), _.getKey(\"length\")]);\n *\n * getDataAmount(someObject, someArrayData); // => 15\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.mapArgs|mapArgs}\n * @since 0.3.0\n * @param {Function} fn\n * @param {Function[]} tappers\n * @returns {Function}\n */\nfunction tapArgs (fn, tappers) {\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.<br/>\n * The first call in this case happens as soon as the function is invoked; see also\n * {@link module:lamb.debounce|debounce} for a different behaviour where the first call is delayed.\n * @example\n * const 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 * @see {@link module:lamb.debounce|debounce}\n * @since 0.1.0\n * @param {Function} fn\n * @param {Number} timespan - Expressed in milliseconds.\n * @returns {Function}\n */\nfunction 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.<br/>\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.\n * @example\n * const weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * _.map(weights, _.unary(parseInt)) // => [2, 10, 1, 7]\n *\n * @memberof module:lamb\n * @category Function\n * @see {@link module:lamb.aritize|aritize}\n * @see {@link module:lamb.binary|binary}\n * @since 0.10.0\n * @param {Function} fn\n * @returns {Function}\n */\nfunction unary (fn) {\n    return function (a) {\n        return fn.call(this, a);\n    };\n}\n\n/**\n * Accepts a series of functions and builds a function that applies the received\n * arguments to each one and returns the first non-<code>undefined</code> value.<br/>\n * Meant to work in synergy with {@link module:lamb.casus|casus} and\n * {@link module:lamb.invoke|invoke}, can be useful as a strategy pattern for functions,\n * to mimic conditional logic or pattern matching, and also to build polymorphic functions.\n * @example\n * const isEven = n => n % 2 === 0;\n * const filterString = _.compose(_.joinWith(\"\"), _.filter);\n * const filterAdapter = _.adapter([\n *     _.invoke(\"filter\"),\n *     _.casus(_.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 * // by its nature is composable\n * const 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 * @see {@link module:lamb.casus|casus}\n * @see {@link module:lamb.invoke|invoke}\n * @since 0.6.0\n * @param {Function[]} functions\n * @returns {Function}\n */\nfunction adapter (functions) {\n    if (!Array.isArray(functions)) {\n        throw _makeTypeErrorFor(functions, \"array\");\n    }\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 * Creates a function to check the given predicates.<br/>\n * Used to build the {@link module:lamb.allOf|allOf} and the\n * {@link module:lamb.anyOf|anyOf} functions.\n * @private\n * @param {Boolean} checkAll\n * @returns {Function}\n */\nfunction _checkPredicates (checkAll) {\n    return function (predicates) {\n        if (!Array.isArray(predicates)) {\n            throw _makeTypeErrorFor(predicates, \"array\");\n        }\n\n        return function () {\n            for (var i = 0, len = predicates.length, result; i < len; i++) {\n                result = predicates[i].apply(this, arguments);\n\n                if (checkAll && !result) {\n                    return false;\n                } else if (!checkAll && result) {\n                    return true;\n                }\n            }\n\n            return checkAll;\n        };\n    };\n}\n\n/**\n * Accepts an array of predicates and builds a new one that returns true if they are all satisfied\n * by the same arguments. The functions in the array will be applied one at a time until a\n * <code>false</code> value is produced, which is returned immediately.\n * @example\n * const isEven = n => n % 2 === 0;\n * const isPositiveEven = _.allOf([isEven, _.isGT(0)]);\n *\n * isPositiveEven(-2) // => false\n * isPositiveEven(11) // => false\n * isPositiveEven(6) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.anyOf|anyOf}\n * @since 0.1.0\n * @param {Function[]} predicates\n * @returns {Function}\n */\nvar allOf = _checkPredicates(true);\n\n/**\n * Accepts an array of predicates and builds a new one that returns true if at least one of them is\n * satisfied by the received arguments. The functions in the array will be applied one at a time\n * until a <code>true</code> value is produced, which is returned immediately.\n * @example\n * const users = [\n *     {id: 1, name: \"John\", group: \"guest\"},\n *     {id: 2, name: \"Jane\", group: \"root\"},\n *     {id: 3, name: \"Mario\", group: \"admin\"}\n * ];\n * const isInGroup = _.partial(_.hasKeyValue, [\"group\"]);\n * const 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 * @function\n * @see {@link module:lamb.allOf|allOf}\n * @since 0.1.0\n * @param {Function[]} predicates\n * @returns {Function}\n */\nvar anyOf = _checkPredicates(false);\n\n/**\n * Verifies that the two supplied values are the same value using the \"SameValue\" comparison.<br/>\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 <code>0</code> and <code>-0</code> aren't the same value and, finally,\n * <code>NaN</code> is equal to itself.<br/>\n * See also {@link module:lamb.is|is} for a curried version building a predicate and\n * {@link module:lamb.areSVZ|areSVZ} and {@link module:lamb.isSVZ|isSVZ} to perform a \"SameValueZero\"\n * comparison.\n * @example\n * const testObject = {};\n *\n * _.areSame({}, testObject) // => false\n * _.areSame(testObject, testObject) // => true\n * _.areSame(\"foo\", \"foo\") // => true\n * _.areSame(0, -0) // => false\n * _.areSame(0 / 0, NaN) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.is|is}\n * @see {@link module:lamb.areSVZ|areSVZ}, {@link module:lamb.isSVZ|isSVZ}\n * @see [SameValue comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevaluezero}\n * @since 0.50.0\n * @param {*} a\n * @param {*} b\n * @returns {Boolean}\n */\nfunction areSame (a, b) {\n    return a === 0 && b === 0 ? 1 / a === 1 / b : areSVZ(a, b);\n}\n\n/**\n * Builds a case for {@link module:lamb.adapter|adapter}.<br/>\n * The function will apply the received arguments to <code>fn</code> if the predicate is satisfied\n * with the same arguments, otherwise will return <code>undefined</code>.<br/>\n * See also {@link module:lamb.condition|condition} to build a condition with two branching functions\n * and {@link module:lamb.unless|unless} and {@link module:lamb.when|when} where one of the branches\n * is the identity function.\n * @example\n * const halveIfNumber = _.casus(_.isType(\"Number\"), _.divideBy(2));\n *\n * halveIfNumber(2) // => 1\n * halveIfNumber(\"2\") // => undefined\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.adapter|adapter}\n * @see {@link module:lamb.condition|condition}\n * @see {@link module:lamb.unless|unless}\n * @see {@link module:lamb.when|when}\n * @since 0.51.0\n * @param {Function} predicate\n * @param {Function} fn\n * @returns {Function}\n */\nfunction casus (predicate, fn) {\n    return function () {\n        return predicate.apply(this, arguments) ? fn.apply(this, arguments) : void 0;\n    };\n}\n\n/**\n * Builds a function that will apply the received arguments to <code>trueFn</code>,\n * if the predicate is satisfied with the same arguments, or to <code>falseFn</code> otherwise.<br/>\n * Although you can use other <code>condition</code>s as <code>trueFn</code> or <code>falseFn</code>,\n * it's probably better to use {@link module:lamb.adapter|adapter} to build more complex behaviours.<br/>\n * See also {@link module:lamb.unless|unless} and {@link module:lamb.when|when} as they are\n * shortcuts to common use cases.\n * @example\n * const isEven = n => n % 2 === 0;\n * const halveEvenAndDoubleOdd = _.condition(isEven, _.divideBy(2), _.multiplyBy(2));\n *\n * halveEvenAndDoubleOdd(5) // => 10\n * halveEvenAndDoubleOdd(6) // => 3\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.unless|unless}\n * @see {@link module:lamb.when|when}\n * @see {@link module:lamb.adapter|adapter}\n * @see {@link module:lamb.casus|casus}\n * @since 0.2.0\n * @param {Function} predicate\n * @param {Function} trueFn\n * @param {Function} falseFn\n * @returns {Function}\n */\nfunction condition (predicate, trueFn, falseFn) {\n    return function () {\n        return (predicate.apply(this, arguments) ? trueFn : falseFn).apply(this, arguments);\n    };\n}\n\n/**\n * Verifies that the first given value is greater than the second.<br/>\n * Wraps the native <code>&gt;</code> operator within a function.\n * @example\n * const pastDate = new Date(2010, 2, 12);\n * const today = new Date();\n *\n * _.gt(today, pastDate) // => true\n * _.gt(pastDate, today) // => false\n * _.gt(3, 4) // => false\n * _.gt(3, 3) // => false\n * _.gt(3, 2) // => true\n * _.gt(0, -0) // => false\n * _.gt(-0, 0) // => false\n * _.gt(\"a\", \"A\") // => true\n * _.gt(\"b\", \"a\") // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.gte|gte}\n * @see {@link module:lamb.lt|lt}, {@link module:lamb.lte|lte}\n * @see {@link module:lamb.isGT|isGT}, {@link module:lamb.isGTE|isGTE}\n * @see {@link module:lamb.isLT|isLT}, {@link module:lamb.isLTE|isLTE}\n * @since 0.50.0\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\nfunction gt (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\n * <code>&gt;=</code> operator, so <code>-0 === 0</code>.\n * @example\n * _.gte(3, 4) // => false\n * _.gte(3, 3) // => true\n * _.gte(3, 2) // => true\n * _.gte(0, -0) // => true\n * _.gte(-0, 0) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.gt|gt}\n * @see {@link module:lamb.lt|lt}, {@link module:lamb.lte|lte}\n * @see {@link module:lamb.isGT|isGT}, {@link module:lamb.isGTE|isGTE}\n * @see {@link module:lamb.isLT|isLT}, {@link module:lamb.isLTE|isLTE}\n * @since 0.50.0\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\nfunction gte (a, b) {\n    return a >= b;\n}\n\n/**\n * A curried version of {@link module:lamb.areSame|areSame}.<br/>\n * Accepts a value and builds a predicate that checks whether the value\n * and the one received by the predicate are the same using the \"SameValue\"\n * comparison.<br/>\n * See also {@link module:lamb.areSVZ|areSVZ} and {@link module:lamb.isSVZ|isSVZ}\n * to perform a \"SameValueZero\" comparison.\n * @example\n * const john = {name: \"John\", surname: \"Doe\"};\n * const isJohn = _.is(john);\n * const isNegativeZero = _.is(-0);\n * const isReallyNaN = _.is(NaN);\n *\n * isJohn(john) // => true\n * isJohn({name: \"John\", surname: \"Doe\"}) // => false\n *\n * isNegativeZero(0) // => false\n * isNegativeZero(-0) // => true\n *\n * isNaN(NaN) // => true\n * isNaN(\"foo\") // => true\n *\n * isReallyNaN(NaN) // => true\n * isReallyNaN(\"foo\") // => false\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.areSame|areSame}\n * @see {@link module:lamb.areSVZ|areSVZ}, {@link module:lamb.isSVZ|isSVZ}\n * @see [SameValue comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevalue}\n * @see [SameValueZero comparison]{@link https://www.ecma-international.org/ecma-262/7.0/#sec-samevaluezero}\n * @since 0.1.0\n * @param {*} value\n * @returns {Function}\n */\nvar is = _curry2(areSame);\n\n/**\n * A right curried version of {@link module:lamb.gt|gt}.<br/>\n * Accepts a value and builds a predicate that checks whether the value\n * is greater than the one received by the predicate.\n * @example\n * const isGreaterThan5 = _.isGT(5);\n *\n * isGreaterThan5(3) // => false\n * isGreaterThan5(5) // => false\n * isGreaterThan5(7) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.isGTE|isGTE}\n * @see {@link module:lamb.isLT|isLT}, {@link module:lamb.isLTE|isLTE}\n * @see {@link module:lamb.gt|gt}, {@link module:lamb.gte|gte}\n * @see {@link module:lamb.lt|lt}, {@link module:lamb.lte|lte}\n * @since 0.1.0\n * @param {Number|String|Date|Boolean} value\n * @returns {Function}\n */\nvar isGT = _curry2(gt, true);\n\n/**\n * A right curried version of {@link module:lamb.gte|gte}.<br/>\n * Accepts a value and builds a predicate that checks whether the value\n * is greater than or equal to the one received by the predicate.\n * @example\n * const isPositiveOrZero = _.isGTE(0);\n *\n * isPositiveOrZero(-3) // => false\n * isPositiveOrZero(-0) // => true\n * isPositiveOrZero(0) // => true\n * isPositiveOrZero(5) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.isGT|isGT}\n * @see {@link module:lamb.isLT|isLT}, {@link module:lamb.isLTE|isLTE}\n * @see {@link module:lamb.gt|gt}, {@link module:lamb.gte|gte}\n * @see {@link module:lamb.lt|lt}, {@link module:lamb.lte|lte}\n * @since 0.1.0\n * @param {Number|String|Date|Boolean} value\n * @returns {Function}\n */\nvar isGTE = _curry2(gte, true);\n\n/**\n * Verifies that the first given value is less than the second.<br/>\n * Wraps the native <code>&lt;</code> operator within a function.\n * @example\n * const pastDate = new Date(2010, 2, 12);\n * const today = new Date();\n *\n * _.lt(today, pastDate) // => false\n * _.lt(pastDate, today) // => true\n * _.lt(3, 4) // => true\n * _.lt(3, 3) // => false\n * _.lt(3, 2) // => false\n * _.lt(0, -0) // => false\n * _.lt(-0, 0) // => false\n * _.lt(\"a\", \"A\") // => false\n * _.lt(\"a\", \"b\") // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.lte|lte}\n * @see {@link module:lamb.gt|gt}, {@link module:lamb.gte|gte}\n * @see {@link module:lamb.isLT|isLT}, {@link module:lamb.isLTE|isLTE}\n * @see {@link module:lamb.isGT|isGT}, {@link module:lamb.isGTE|isGTE}\n * @since 0.50.0\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\nfunction lt (a, b) {\n    return a < b;\n}\n\n/**\n * A right curried version of {@link module:lamb.lt|lt}.<br/>\n * Accepts a value and builds a predicate that checks whether the value\n * is less than the one received by the predicate.\n * @example\n * const isLessThan5 = _.isLT(5);\n *\n * isLessThan5(7) // => false\n * isLessThan5(5) // => false\n * isLessThan5(3) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.isLTE|isLTE}\n * @see {@link module:lamb.isGT|isGT}, {@link module:lamb.isGTE|isGTE}\n * @see {@link module:lamb.lt|lt}, {@link module:lamb.lte|lte}\n * @see {@link module:lamb.gt|gt}, {@link module:lamb.gte|gte}\n * @since 0.1.0\n * @param {Number|String|Date|Boolean} value\n * @returns {Function}\n */\nvar isLT = _curry2(lt, true);\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\n * <code>&lt;=</code> operator, so <code>-0 === 0</code>.\n * @example\n * _.lte(3, 4) // => true\n * _.lte(3, 3) // => true\n * _.lte(3, 2) // => false\n * _.lte(0, -0) // => true\n * _.lte(-0, 0) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.lt|lt}\n * @see {@link module:lamb.gt|gt}, {@link module:lamb.gte|gte}\n * @see {@link module:lamb.isLT|isLT}, {@link module:lamb.isLTE|isLTE}\n * @see {@link module:lamb.isGT|isGT}, {@link module:lamb.isGTE|isGTE}\n * @since 0.50.0\n * @param {Number|String|Date|Boolean} a\n * @param {Number|String|Date|Boolean} b\n * @returns {Boolean}\n */\nfunction lte (a, b) {\n    return a <= b;\n}\n\n/**\n * A right curried version of {@link module:lamb.lte|lte}.<br/>\n * Accepts a value and builds a predicate that checks whether the value\n * is less than or equal to the one received by the predicate.\n * @example\n * const isNegativeOrZero = _.isLTE(0);\n *\n * isNegativeOrZero(5) // => false\n * isNegativeOrZero(-0) // => true\n * isNegativeOrZero(0) // => true\n * isNegativeOrZero(-3) // => true\n *\n * @memberof module:lamb\n * @category Logic\n * @function\n * @see {@link module:lamb.isLT|isLT}\n * @see {@link module:lamb.isGT|isGT}, {@link module:lamb.isGTE|isGTE}\n * @see {@link module:lamb.lt|lt}, {@link module:lamb.lte|lte}\n * @see {@link module:lamb.gt|gt}, {@link module:lamb.gte|gte}\n * @since 0.1.0\n * @param {Number|String|Date|Boolean} value\n * @returns {Function}\n */\nvar isLTE = _curry2(lte, true);\n\n/**\n * Returns a predicate that negates the given one.\n * @example\n * const isEven = n => n % 2 === 0;\n * const isOdd = _.not(isEven);\n *\n * isOdd(5) // => true\n * isOdd(4) // => false\n *\n * @memberof module:lamb\n * @category Logic\n * @since 0.1.0\n * @param {Function} predicate\n * @returns {Function}\n */\nfunction not (predicate) {\n    return function () {\n        return !predicate.apply(this, arguments);\n    };\n}\n\n/**\n * Builds a unary function that will check its argument against the given predicate.\n * If the predicate isn't satisfied, the provided <code>fn</code> function will be\n * applied to the same value. The received argument is returned as it is otherwise.<br/>\n * See {@link module:lamb.when|when} for the opposite behaviour.<br/>\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its <code>trueFn</code> parameter is the [identity function]{@link module:lamb.identity}.\n * @example\n * const isEven = n => n % 2 === 0;\n * const halveUnlessIsEven = _.unless(isEven, _.divideBy(2));\n *\n * halveUnlessIsEven(5) // => 2.5\n * halveUnlessIsEven(6) // => 6\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.condition|condition}\n * @see {@link module:lamb.when|when}\n * @see {@link module:lamb.adapter|adapter}\n * @see {@link module:lamb.casus|casus}\n * @since 0.42.0\n * @param {Function} predicate\n * @param {Function} fn\n * @returns {Function}\n */\nfunction unless (predicate, fn) {\n    return function (value) {\n        return predicate.call(this, value) ? value : fn.call(this, value);\n    };\n}\n\n/**\n * Builds a unary function that will check its argument against the given predicate.\n * If the predicate is satisfied, the provided <code>fn</code> function will be\n * applied to the same value. The received argument is returned as it is otherwise.<br/>\n * See {@link module:lamb.unless|unless} for the opposite behaviour.<br/>\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its <code>falseFn</code> parameter is the [identity function]{@link module:lamb.identity}.\n * @example\n * const isEven = n => n % 2 === 0;\n * const halveIfEven = _.when(isEven, _.divideBy(2));\n *\n * halveIfEven(5) // => 5\n * halveIfEven(6) // => 3\n *\n * @memberof module:lamb\n * @category Logic\n * @see {@link module:lamb.condition|condition}\n * @see {@link module:lamb.unless|unless}\n * @see {@link module:lamb.adapter|adapter}\n * @see {@link module:lamb.casus|casus}\n * @since 0.42.0\n * @param {Function} predicate\n * @param {Function} fn\n * @returns {Function}\n */\nfunction when (predicate, fn) {\n    return function (value) {\n        return predicate.call(this, value) ? fn.call(this, value) : value;\n    };\n}\n\n/**\n * Sums two numbers.\n * @example\n * _.sum(4, 5) // => 9\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.add|add}\n * @since 0.50.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\nfunction sum (a, b) {\n    return a + b;\n}\n\n/**\n * A curried version of {@link module:lamb.sum|sum}.\n * @example\n * const add5 = _.add(5);\n *\n * _.add5(4) // => 9\n * _.add5(-2) // => 3\n *\n * @memberof module:lamb\n * @category Math\n * @function\n * @see {@link module:lamb.sum|sum}\n * @since 0.1.0\n * @param {Number} a\n * @returns {Function}\n */\nvar add = _curry2(sum, true);\n\n/**\n * Subtracts two numbers.\n * @example\n * _.subtract(5, 3) // => 2\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.deduct|deduct}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\nfunction subtract (a, b) {\n    return a - b;\n}\n\n/**\n * A curried version of {@link module:lamb.subtract|subtract} that expects the\n * subtrahend to build a function waiting for the minuend.\n * @example\n * const deduct5 = _.deduct(5);\n *\n * deduct5(12) // => 7\n * deduct5(3) // => -2\n *\n * @memberof module:lamb\n * @category Math\n * @function\n * @see {@link module:lamb.subtract|subtract}\n * @since 0.50.0\n * @param {Number} a\n * @returns {Function}\n */\nvar deduct = _curry2(subtract, true);\n\n/**\n * Divides two numbers.\n * @example\n * _.divide(5, 2) // => 2.5\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.divideBy|divideBy}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\nfunction divide (a, b) {\n    return a / b;\n}\n\n/**\n * A curried version of {@link module:lamb.divide|divide} that expects a divisor to\n * build a function waiting for the dividend.\n * @example\n * const halve = divideBy(2);\n *\n * halve(10) // => 5\n * halve(5) // => 2.5\n *\n * @memberof module:lamb\n * @category Math\n * @function\n * @see {@link module:lamb.divide|divide}\n * @since 0.50.0\n * @param {Number} a\n * @returns {Function}\n */\nvar divideBy = _curry2(divide, true);\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 * const fibonacci = (n, idx, results) => n + (results[idx - 1] || 0);\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 * @see {@link module:lamb.range|range}\n * @since 0.21.0\n * @param {*} start - The starting value\n * @param {Number} len - The desired length for the sequence\n * @param {ListIteratorCallback} iteratee\n * @returns {Array}\n */\nfunction generate (start, len, iteratee) {\n    var result = [start];\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 * Verifies whether the received value is a finite number.<br/>\n * Behaves almost as a shim of ES6's [Number.isFinite]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite},\n * but with a difference: it will return <code>true</code> even for Number object's instances.\n * @example\n * _.isFinite(5) // => true\n * _.isFinite(new Number(5)) // => true\n * _.isFinite(Infinity) // => false\n * _.isFinite(-Infinity) // => false\n * _.isFinite(\"5\") // => false\n * _.isFinite(NaN) // => false\n * _.isFinite(null) // => false\n *\n * @alias module:lamb.isFinite\n * @category Math\n * @since 0.46.0\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isFinite_ (value) {\n    return type(value) === \"Number\" && isFinite(value);\n}\n\n/**\n * Verifies whether the received value is a number and an integer.\n * Behaves almost as a shim of ES6's [Number.isInteger]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger},\n * but with a difference: it will return <code>true</code> even for Number object's instances.\n * @example\n * _.isInteger(5) // => true\n * _.isInteger(new Number(5)) // => true\n * _.isInteger(2.5) // => false\n * _.isInteger(Infinity) // => false\n * _.isInteger(-Infinity) // => false\n * _.isInteger(\"5\") // => false\n * _.isInteger(NaN) // => false\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.isSafeInteger|isSafeInteger}\n * @since 0.46.0\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isInteger (value) {\n    return type(value) === \"Number\" && value % 1 === 0;\n}\n\n/**\n * Verifies whether the received value is a \"safe integer\", meaning that is a number and that\n * can be exactly represented as an IEEE-754 double precision number.\n * The safe integers consist of all integers from -(2<sup>53</sup> - 1) inclusive to\n * 2<sup>53</sup> - 1 inclusive.<br/>\n * Behaves almost as a shim of ES6's [Number.isSafeInteger]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger},\n * but with a difference: it will return <code>true</code> even for Number object's instances.\n * @example\n * _.isSafeInteger(5) // => true\n * _.isSafeInteger(new Number(5)) // => true\n * _.isSafeInteger(Math.pow(2, 53) - 1) // => true\n * _.isSafeInteger(Math.pow(2, 53)) // => false\n * _.isSafeInteger(2e32) // => false\n * _.isSafeInteger(2.5) // => false\n * _.isSafeInteger(Infinity) // => false\n * _.isSafeInteger(-Infinity) // => false\n * _.isSafeInteger(\"5\") // => false\n * _.isSafeInteger(NaN) // => false\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.isInteger|isInteger}\n * @since 0.46.0\n * @param {*} value\n * @returns {Boolean}\n */\nfunction isSafeInteger (value) {\n    return isInteger(value) && Math.abs(value) <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Calculates the [arithmetic mean]{@link https://en.wikipedia.org/wiki/Arithmetic_mean} of the given list of numbers.\n * @example\n * _.mean([1, 2, 3, 4, 5, 6, 7, 8, 9]) // => 5\n * _.mean([]) // => NaN\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.median|median}\n * @since 0.60.0\n * @param {Number[]} numbers\n * @returns {Number}\n */\nfunction mean (numbers) {\n    return reduce(numbers, function (r, n) {\n        return +n + r;\n    }, 0) / numbers.length;\n}\n\n/**\n * Calculates the [median]{@link https://en.wikipedia.org/wiki/Median} of the given list of numbers.\n * @example\n * _.median([10, 2, 3, 1, 4, 5, 7]) // => 4\n * _.median([]) // => NaN\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.mean|mean}\n * @since 0.60.0\n * @param {Number[]} numbers\n * @returns {Number}\n */\nfunction median (numbers) {\n    var len = numbers.length >>> 0;\n\n    if (len === 0) {\n        return NaN;\n    }\n\n    var result;\n    var sortedNumbers = map(numbers, Number).sort(subtract);\n\n    if (len % 2 === 0) {\n        var pivot = len / 2;\n\n        result = (sortedNumbers[pivot - 1] + sortedNumbers[pivot]) / 2;\n    } else {\n        result = sortedNumbers[(len - 1) / 2];\n    }\n\n    return result;\n}\n\n/**\n * Performs the modulo operation and should not be confused with the\n * {@link module:lamb.remainder|remainder}.\n * The function performs a floored division to calculate the result and not\n * a truncated one, hence the sign of the dividend is not kept, unlike the\n * {@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 module:lamb.remainder|remainder}\n * @see [Modulo operation on Wikipedia]{@link http://en.wikipedia.org/wiki/Modulo_operation}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\nfunction 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 * @see {@link module:lamb.multiplyBy|multiplyBy}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\nfunction multiply (a, b) {\n    return a * b;\n}\n\n/**\n * A curried version of {@link module:lamb.multiply|multiply}.\n * @example\n * const double = _.multiplyBy(2);\n *\n * double(5) // => 10\n *\n * @memberof module:lamb\n * @category Math\n * @function\n * @see {@link module:lamb.multiply|multiply}\n * @since 0.50.0\n * @param {Number} a\n * @returns {Function}\n */\nvar multiplyBy = _curry2(multiply, true);\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 <code>randomInt(0.1, 1.2)</code> could be <code>2</code>.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @since 0.1.0\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\nfunction randomInt (min, max) {\n    return Math.floor(Math.random() * (max - min + 1) + min);\n}\n\n/**\n * Converts a value to a number and returns it if it's not NaN, otherwise\n * returns zero.\n * @private\n * @param {*} value\n * @returns {Number}\n */\nfunction _forceToNumber (value) {\n    var n = +value;\n\n    return n === n ? n : 0; // eslint-disable-line no-self-compare\n}\n\n/**\n * Generates an arithmetic progression of numbers starting from <code>start</code> up to,\n * but not including, <code>limit</code>, using the given <code>step</code>.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(1, -10, -2) // => [1, -1, -3, -5, -7, -9]\n * _.range(0, 3, 1) // => [0, 1, 2]\n * _.range(-0, 3, 1) // => [-0, 1, 2]\n * _.range(1, -10, 2) // => []\n * _.range(3, 5, -1) // => []\n *\n * @example <caption>Behaviour if <code>step</code> happens to be zero:</caption>\n * _.range(2, 10, 0) // => [2]\n * _.range(2, -10, 0) // => [2]\n * _.range(2, 2, 0) // => []\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.generate|generate}\n * @since 0.1.0\n * @param {Number} start\n * @param {Number} limit\n * @param {Number} [step=1]\n * @returns {Number[]}\n */\nfunction range (start, limit, step) {\n    start = _forceToNumber(start);\n    limit = _forceToNumber(limit);\n    step = arguments.length === 3 ? _forceToNumber(step) : 1;\n\n    if (step === 0) {\n        return limit === start ? [] : [start];\n    }\n\n    var len = Math.max(Math.ceil((limit - start) / step), 0);\n    var result = Array(len);\n\n    for (var i = 0, last = start; i < len; i++) {\n        result[i] = last;\n        last += step;\n    }\n\n    return result;\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 * const isOdd = n => _.remainder(n, 2) === 1;\n *\n * isOdd(-3) // => false as -3 % 2 === -1\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.modulo|modulo}\n * @see [Modulo operation on Wikipedia]{@link http://en.wikipedia.org/wiki/Modulo_operation}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\nfunction remainder (a, b) {\n    return a % b;\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} source\n * @param {String} key\n * @returns {Boolean}\n */\nvar _isOwnEnumerable = generic(Object.prototype.propertyIsEnumerable);\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} source\n * @returns {String[]}\n */\nfunction _safeEnumerables (source) {\n    var result = [];\n\n    for (var key in source) {\n        result.push(key);\n    }\n\n    return result;\n}\n\n/**\n * Checks whether the specified key is an enumerable property of the given object or not.\n * @private\n * @param {Object} source\n * @param {String} key\n * @returns {Boolean}\n */\nfunction _isEnumerable (source, key) {\n    return key in Object(source) && (_isOwnEnumerable(source, key) || ~_safeEnumerables(source).indexOf(key));\n}\n\n/**\n * Helper to retrieve the correct key while evaluating a path.\n * @private\n * @param {Object} target\n * @param {String} key\n * @param {Boolean} includeNonEnumerables\n * @returns {String|Number|Undefined}\n */\nfunction _getPathKey (target, key, includeNonEnumerables) {\n    if (includeNonEnumerables && key in Object(target) || _isEnumerable(target, key)) {\n        return key;\n    }\n\n    var n = +key;\n    var len = target && target.length;\n\n    return n >= -len && n < len ? n < 0 ? n + len : n : void 0;\n}\n\n/**\n * Checks if a path is valid in the given object and retrieves the path target.\n * @private\n * @param {Object} source\n * @param {String[]} parts\n * @param {Boolean} walkNonEnumerables\n * @returns {Object}\n */\nfunction _getPathInfo (source, parts, walkNonEnumerables) {\n    if (isNil(source)) {\n        throw _makeTypeErrorFor(source, \"object\");\n    }\n\n    var target = source;\n    var i = -1;\n    var len = parts.length;\n    var key;\n\n    while (++i < len) {\n        key = _getPathKey(target, parts[i], walkNonEnumerables);\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 * 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 */\nfunction _toPathParts (path, separator) {\n    return String(path).split(separator || \".\");\n}\n\n/**\n * Gets a nested property value from an object using the given path.<br/>\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.<br/>\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 * const 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 <caption>Accessing array-like objects indexes:</caption>\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 <caption>Priority will be given to existing object keys over indexes:</caption>\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 * @since 0.19.0\n * @param {Object|ArrayLike} source\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {*}\n */\nfunction getPathIn (source, path, separator) {\n    return _getPathInfo(source, _toPathParts(path, separator), true).target;\n}\n\n/**\n * Builds a <code>checker</code> function meant to be used with\n * {@link module:lamb.validate|validate}.<br/>\n * Note that the function accepts multiple <code>keyPaths</code> as a means to\n * compare their values. In other words all the received <code>keyPaths</code> will be\n * passed as arguments to the <code>predicate</code> to run the test.<br/>\n * If you want to run the same single property check with multiple properties, you should build\n * multiple <code>checker</code>s and combine them with {@link module:lamb.validate|validate}.\n * @example\n * const user = {\n *     name: \"John\",\n *     surname: \"Doe\",\n *     login: {\n *         username: \"jdoe\",\n *         password: \"abc123\",\n *         passwordConfirm: \"abc123\"\n *     }\n * };\n * const pwdMatch = _.checker(\n *     _.areSame,\n *     \"Passwords don't match\",\n *     [\"login.password\", \"login.passwordConfirm\"]\n * );\n *\n * pwdMatch(user) // => []\n *\n * const 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 * @since 0.1.0\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 keys, or {@link module:lamb.getPathIn|paths}, to test.\n * @param {String} [pathSeparator=\".\"]\n * @returns {Function} A checker function which returns an error in the form\n * <code>[\"message\", [\"propertyA\", \"propertyB\"]]</code> or an empty array.\n */\nfunction checker (predicate, message, keyPaths, pathSeparator) {\n    return function (obj) {\n        var getValues = partial(getPathIn, [obj, __, pathSeparator]);\n\n        return predicate.apply(obj, map(keyPaths, getValues)) ? [] : [message, keyPaths];\n    };\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 */\nvar _unsafeKeyListFrom = _curry2(function (getKeys, source) {\n    if (isNil(source)) {\n        throw _makeTypeErrorFor(source, \"object\");\n    }\n\n    return getKeys(source);\n});\n\n/**\n * Creates an array with all the enumerable properties of the given object.\n * @example <caption>Showing the difference with {@link module:lamb.keys|keys}:</caption>\n * const baseFoo = Object.create({a: 1}, {b: {value: 2}});\n * const 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 * @since 0.12.0\n * @param {Object} source\n * @returns {String[]}\n */\nvar enumerables = _unsafeKeyListFrom(_safeEnumerables);\n\n/**\n * Builds an object from a list of key / value pairs like the one\n * returned by {@link module:lamb.pairs|pairs} or {@link module:lamb.ownPairs|ownPairs}.<br/>\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 * @see {@link module:lamb.ownPairs|ownPairs}, {@link module:lamb.pairs|pairs}\n * @since 0.8.0\n * @param {Array<Array<String, *>>} pairsList\n * @returns {Object}\n */\nfunction 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 * Builds a partial application of {@link module:lamb.getPathIn|getPathIn} with the given\n * path and separator, expecting the object to act upon.<br/>\n * @example\n * const user = {\n *     name: \"John\",\n *     surname: \"Doe\",\n *     login: {\n *         \"user.name\": \"jdoe\",\n *         password: \"abc123\"\n *     }\n * };\n *\n * const getPwd = _.getPath(\"login.password\");\n * const getUsername = _.getPath(\"login/user.name\", \"/\");\n *\n * getPwd(user) // => \"abc123\";\n * getUsername(user) // => \"jdoe\"\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.getPathIn|getPathIn}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @since 0.19.0\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\nvar getPath = _makePartial3(getPathIn);\n\n/**\n * Verifies the existence of a property in an sourceect.\n * @example\n * const user1 = {name: \"john\"};\n *\n * _.has(user1, \"name\") // => true\n * _.has(user1, \"surname\") // => false\n * _.has(user1, \"toString\") // => true\n *\n * const 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 * @see {@link module:lamb.hasKey|hasKey}\n * @see {@link module:lamb.hasOwn|hasOwn}, {@link module:lamb.hasOwnKey|hasOwnKey}\n * @see {@link module:lamb.pathExistsIn|pathExistsIn}, {@link module:lamb.pathExists|pathExists}\n * @since 0.1.0\n * @param {Object} source\n * @param {String} key\n * @returns {Boolean}\n */\nfunction has (source, key) {\n    if (typeof source !== \"object\" && !isUndefined(source)) {\n        source = Object(source);\n    }\n\n    return key in source;\n}\n\n/**\n * Curried version of {@link module:lamb.has|has}.<br/>\n * Returns a function expecting the object to check against the given key.\n * @example\n * const user1 = {name: \"john\"};\n * const user2 = {};\n * const hasName = _.hasKey(\"name\");\n *\n * hasName(user1) // => true\n * hasName(user2) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.has|has}\n * @see {@link module:lamb.hasOwn|hasOwn}, {@link module:lamb.hasOwnKey|hasOwnKey}\n * @see {@link module:lamb.pathExistsIn|pathExistsIn}, {@link module:lamb.pathExists|pathExists}\n * @since 0.1.0\n * @param {String} key\n * @returns {Function}\n */\nvar hasKey = _curry2(has, true);\n\n/**\n * Verifies if an object has the specified property and that the property isn't inherited through\n * the prototype chain.<br/>\n * @example <caption>Comparison with <code>has</code>:</caption>\n * const 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 * @see {@link module:lamb.hasOwnKey|hasOwnKey}\n * @see {@link module:lamb.has|has}, {@link module:lamb.hasKey|hasKey}\n * @see {@link module:lamb.pathExistsIn|pathExistsIn}, {@link module:lamb.pathExists|pathExists}\n * @since 0.1.0\n * @param {Object} source\n * @param {String} key\n * @returns {Boolean}\n */\nvar hasOwn = generic(Object.prototype.hasOwnProperty);\n\n/**\n * Curried version of {@link module:lamb.hasOwn|hasOwn}.<br/>\n * Returns a function expecting the object to check against the given key.\n * @example\n * const user = {name: \"john\"};\n * const hasOwnName = _.hasOwnKey(\"name\");\n * const hasOwnToString = _.hasOwnToString(\"toString\");\n *\n * hasOwnName(user) // => true\n * hasOwnToString(user) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.hasOwn|hasOwn}\n * @see {@link module:lamb.has|has}, {@link module:lamb.hasKey|hasKey}\n * @see {@link module:lamb.pathExistsIn|pathExistsIn}, {@link module:lamb.pathExists|pathExists}\n * @since 0.1.0\n * @param {String} key\n * @returns {Function}\n */\nvar hasOwnKey = _curry2(hasOwn, true);\n\n/**\n * Builds a predicate expecting an object to check against the given key / value pair.<br/>\n * The value check is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.\n * @example\n * const hasTheCorrectAnswer = _.hasKeyValue(\"answer\", 42);\n *\n * hasTheCorrectAnswer({answer: 2}) // false\n * hasTheCorrectAnswer({answer: 42}) // true\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.hasPathValue|hasPathValue}\n * @since 0.1.0\n * @param {String} key\n * @param {*} value\n * @returns {Function}\n */\nfunction hasKeyValue (key, value) {\n    return function (source) {\n        return isUndefined(value)\n            ? has(source, key) && source[key] === value\n            : areSVZ(value, source[key]);\n    };\n}\n\n/**\n * Builds a predicate to check if the given path exists in an sourceect and holds the desired value.<br/>\n * The value check is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.<br/>\n * Note that the function will check even non-enumerable properties.\n * @example\n * const user = {\n *     name: \"John\",\n *     surname: \"Doe\",\n *     personal: {\n *         age: 25,\n *         gender: \"M\"\n *     },\n *     scores: [\n *         {id: 1, value: 10, passed: false},\n *         {id: 2, value: 20, passed: false},\n *         {id: 3, value: 30, passed: true}\n *     ]\n * };\n *\n * const isMale = _.hasPathValue(\"personal.gender\", \"M\");\n * const hasPassedFirstTest = _.hasPathValue(\"scores.0.passed\", true);\n * const hasPassedLastTest = _.hasPathValue(\"scores.-1.passed\", true);\n *\n * isMale(user) // => true\n * hasPassedFirstTest(user) // => false\n * hasPassedLastTest(user) // => true\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.hasKeyValue|hasKeyValue}\n * @since 0.41.0\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\nfunction hasPathValue (path, value, separator) {\n    return function (source) {\n        var pathInfo = _getPathInfo(source, _toPathParts(path, separator), true);\n\n        return pathInfo.isValid && areSVZ(pathInfo.target, value);\n    };\n}\n\n/**\n * A null-safe version of <code>Object.keys</code>.\n * @private\n * @function\n * @param {Object} source\n * @returns {String[]}\n */\nvar _safeKeys = compose(Object.keys, Object);\n\n/**\n * Retrieves the list of the own enumerable properties of an object.<br/>\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.<br/>\n * This function <em>shims</em> the ECMAScript 6 version, by forcing a conversion to\n * object for any value but <code>null</code> and <code>undefined</code>.\n * @example <caption>Showing the difference with {@link module:lamb.enumerables|enumerables}:</caption>\n * const baseFoo = Object.create({a: 1}, {b: {value: 2}});\n * const 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 * @since 0.25.1\n * @param {Object} source\n * @returns {String[]}\n */\nvar keys = _unsafeKeyListFrom(_safeKeys);\n\n/**\n * Builds a predicate to check if the given key satisfies the desired condition\n * on an object.\n * @example\n * const users = [\n *     {name: \"John\", age: 25},\n *     {name: \"Jane\", age: 15},\n * ];\n * const isAdult = _.keySatisfies(_.isGTE(18), \"age\");\n *\n * isAdult(users[0]) // => true\n * isAdult(users[1]) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pathSatisfies|pathSatisfies}\n * @since 0.45.0\n * @param {Function} predicate\n * @param {String} key\n * @returns {Function}\n */\nfunction keySatisfies (predicate, key) {\n    return function (source) {\n        return predicate.call(this, source[key]);\n    };\n}\n\n/**\n * Builds an object from the two given lists, using the first one as keys and the last\n * one as values.<br/>\n * If the list of keys is longer than the values one, the keys will be created with\n * <code>undefined</code> values.<br/>\n * If more values than keys are supplied, the extra values will be ignored.\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 * @see {@link module:lamb.tear|tear}, {@link module:lamb.tearOwn|tearOwn} for the reverse operation\n * @since 0.8.0\n * @param {String[]} names\n * @param {ArrayLike} values\n * @returns {Object}\n */\nfunction make (names, values) {\n    var result = {};\n    var valuesLen = values.length;\n\n    for (var i = 0, len = names.length; i < len; i++) {\n        result[names[i]] = i < valuesLen ? values[i] : void 0;\n    }\n\n    return result;\n}\n\n/**\n * Creates a new object by applying the given function\n * to all enumerable properties of the source one.\n * @example\n * const weights = {\n *     john: \"72.5 Kg\",\n *     jane: \"52.3 Kg\"\n * };\n *\n * _.mapValues(weights, parseFloat) // => {john: 72.5, jane: 52.3}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.mapValuesWith|mapValuesWith}\n * @since 0.54.0\n * @param {Object} source\n * @param {ObjectIteratorCallback} fn\n * @returns {Object}\n */\nfunction mapValues (source, fn) {\n    if (isNil(source)) {\n        throw _makeTypeErrorFor(source, \"object\");\n    }\n\n    var result = {};\n\n    for (var key in source) {\n        result[key] = fn(source[key], key, source);\n    }\n\n    return result;\n}\n\n/**\n * A curried version of {@link module:lamb.mapValues|mapValues}.<br/>\n * Expects a mapping function to build a new function waiting for the\n * object to act upon.\n * @example\n * const incValues = _.mapValuesWith(_.add(1));\n * const results = {\n *     first: 10,\n *     second: 5,\n *     third: 3\n * };\n *\n * incValues(results) // => {first: 11, second: 6, third: 4}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.mapValues|mapValues}\n * @since 0.54.0\n * @function\n * @param {ObjectIteratorCallback} fn\n * @returns {Function}\n */\nvar mapValuesWith = _curry2(mapValues, true);\n\n/**\n * Merges the received objects using the provided function to retrieve their keys.\n * @private\n * @param {Function} getKeys\n * @param {Object} a\n * @param {Object} b\n * @returns {Function}\n */\nfunction _merge (getKeys, a, b) {\n    return reduce([a, b], function (result, source) {\n        forEach(getKeys(source), function (key) {\n            result[key] = source[key];\n        });\n\n        return result;\n    }, {});\n}\n\n/**\n * Merges the enumerable properties of the provided sources into a new object.<br/>\n * In case of key homonymy the last source has precedence over the first.\n * @example\n * _.merge({a: 1, b: 3}, {b: 5, c: 4}) // => {a: 1, b: 5, c: 4}\n *\n * @example <caption>Array-like objects will be transformed to objects with numbers as keys:</caption>\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 <caption>Every other non-nil value will be treated as an empty object:</caption>\n * _.merge({a: 2}, 99) // => {a: 2}\n * _.merge({a: 2}, NaN) // => {a: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.mergeOwn|mergeOwn} to merge own properties only\n * @since 0.10.0\n * @function\n * @param {Object} a\n * @param {Object} b\n * @returns {Object}\n */\nvar merge = partial(_merge, [enumerables]);\n\n/**\n * Same as {@link module:lamb.merge|merge}, but only the own properties of the\n * sources are taken into account.\n * @example <caption>Showing the difference with <code>merge</code>:</caption>\n * const baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * const foo = Object.create(baseFoo, {\n *     c: {value: 3, enumerable: true}\n * });\n *\n * const 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 <caption>Array-like objects will be transformed to objects with numbers as keys:</caption>\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 <caption>Every other non-nil value will be treated as an empty object:</caption>\n * _.mergeOwn({a: 2}, 99) // => {a: 2}\n * _.mergeOwn({a: 2}, NaN) // => {a: 2}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.merge|merge} to merge all enumerable properties\n * @since 0.12.0\n * @function\n * @param {Object} a\n * @param {Object} b\n * @returns {Object}\n */\nvar mergeOwn = partial(_merge, [keys]);\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 * @function\n * @param {Object} source\n * @returns {Function}\n */\nvar _keyToPairIn = _curry2(function (source, key) {\n    return [key, source[key]];\n});\n\n/**\n * Using the provided function to retrieve the keys, builds a new function\n * expecting an object to create a list of key / value pairs.\n * @private\n * @function\n * @param {Function} getKeys\n * @returns {Function}\n */\nvar _pairsFrom = _curry2(function (getKeys, source) {\n    return map(getKeys(source), _keyToPairIn(source));\n});\n\n/**\n * Same as {@link module:lamb.pairs|pairs}, but only the own enumerable properties of the object are\n * taken into account.<br/>\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example <caption>Showing the difference with <code>pairs</code>:</caption>\n * const baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * const 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 * @see {@link module:lamb.pairs|pairs}\n * @see {@link module:lamb.fromPairs|fromPairs}\n * @since 0.12.0\n * @param {Object} source\n * @returns {Array<Array<String, *>>}\n */\nvar ownPairs = _pairsFrom(keys);\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 */\nvar _valuesFrom = _curry2(function (getKeys, source) {\n    return map(getKeys(source), function (key) {\n        return source[key];\n    });\n});\n\n/**\n * Same as {@link module:lamb.values|values}, but only the own enumerable properties of the object are\n * taken into account.<br/>\n * @example <caption>Showing the difference with <code>values</code>:</caption>\n * const baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * const 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 * @see {@link module:lamb.values|values}\n * @since 0.12.0\n * @param {Object} source\n * @returns {Array}\n */\nvar ownValues = _valuesFrom(keys);\n\n/**\n * Converts an object into an array of key / value pairs of its enumerable properties.<br/>\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 * @see {@link module:lamb.ownPairs|ownPairs}\n * @see {@link module:lamb.fromPairs|fromPairs}\n * @since 0.8.0\n * @param {Object} source\n * @returns {Array<Array<String, *>>}\n */\nvar pairs = _pairsFrom(enumerables);\n\n/**\n * Checks if the provided path exists in the given object.<br/>\n * Note that the function will check even non-enumerable properties.\n * @example\n * const user = {\n *     name: \"John\",\n *     surname: \"Doe\",\n *     address: {\n *         city: \"New York\"\n *     },\n *     scores: [10, 20, 15]\n * };\n *\n * _.pathExistsIn(user, \"address.city\") // => true\n * _.pathExistsIn(user, \"address.country\") // => false\n * _.pathExistsIn(user, \"scores.1\") // => true\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pathExists|pathExists}\n * @see {@link module:lamb.hasOwn|hasOwn}, {@link module:lamb.hasOwnKey|hasOwnKey}\n * @see {@link module:lamb.has|has}, {@link module:lamb.hasKey|hasKey}\n * @since 0.43.0\n * @param {Object} source\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {Boolean}\n */\nfunction pathExistsIn (source, path, separator) {\n    return _getPathInfo(source, _toPathParts(path, separator), true).isValid;\n}\n\n/**\n * Builds a partial application of {@link module:lamb.pathExistsIn|pathExistsIn} using the given\n * path and the optional separator. The resulting function expects the object to check.<br/>\n * Note that the function will check even non-enumerable properties.\n * @example\n * const user = {\n *     name: \"John\",\n *     surname: \"Doe\",\n *     address: {\n *         city: \"New York\"\n *     },\n *     scores: [10, 20, 15]\n * };\n *\n * const hasCity = _.pathExists(\"address.city\");\n * const hasCountry = _.pathExists(\"address.country\");\n * const hasAtLeastThreeScores = _.pathExists(\"scores.2\");\n *\n * hasCity(user) // => true\n * hasCountry(user) // => false\n * hasAtLeastThreeScores(user) // => true\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.pathExistsIn|pathExistsIn}\n * @see {@link module:lamb.hasOwn|hasOwn}, {@link module:lamb.hasOwnKey|hasOwnKey}\n * @see {@link module:lamb.has|has}, {@link module:lamb.hasKey|hasKey}\n * @since 0.43.0\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\nvar pathExists = _makePartial3(pathExistsIn);\n\n/**\n * Builds a predicate that verifies if a condition is satisfied for the given\n * path in an object.<br/>\n * Like the other \"path functions\" you can use integers in the path, even\n * negative ones, to refer to array-like object indexes, but the priority will\n * be given to existing object keys.\n * @example\n * const user = {\n *     name: \"John\",\n *     performance: {\n *         scores: [1, 5, 10]\n *     }\n * };\n *\n * const gotAnHighScore = _.pathSatisfies(_.contains(10), \"performance.scores\");\n * const hadAGoodStart = _.pathSatisfies(_.isGT(6), \"performance.scores.0\");\n *\n * gotAnHighScore(user) // => true\n * hadAGoodStart(user) // => false\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.keySatisfies|keySatisfies}\n * @since 0.45.0\n * @param {Function} predicate\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\nfunction pathSatisfies (predicate, path, separator) {\n    return function (source) {\n        var pathInfo = _getPathInfo(source, _toPathParts(path, separator), true);\n\n        return predicate.call(this, pathInfo.target);\n    };\n}\n\n/**\n * Returns an object containing only the specified properties of the given object.<br/>\n * Non existent properties will be ignored.\n * @example\n * const user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.pickIn(user, [\"name\", \"age\"]) // => {\"name\": \"john\", \"age\": 30};\n * _.pickIn(user, [\"name\", \"email\"]) // => {\"name\": \"john\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.pickIf|pickIf}, {@link module:lamb.pick|pick}\n * @see {@link module:lamb.skipIn|skipIn}, {@link module:lamb.skipIf|skipIf}\n * @since 0.1.0\n * @param {Object} source\n * @param {String[]} whitelist\n * @returns {Object}\n */\nfunction pickIn (source, whitelist) {\n    var result = {};\n\n    for (var i = 0, len = whitelist.length, key; i < len; i++) {\n        key = whitelist[i];\n\n        if (has(source, key)) {\n            result[key] = source[key];\n        }\n    }\n\n    return result;\n}\n\n/**\n * A curried version of {@link module:lamb.pickIn|pickIn}, expecting a whitelist of keys to build\n * a function waiting for the object to act upon.\n * @example\n * const user = {id: 1, name: \"Jane\", surname: \"Doe\", active: false};\n * const getUserInfo = _.pick([\"id\", \"active\"]);\n *\n * getUserInfo(user) // => {id: 1, active: false}\n *\n * @example <caption>A useful composition with <code>mapWith</code>:</caption>\n * const 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 * const select = _.compose(_.mapWith, _.pick);\n * const 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.pickIn|pickIn}, {@link module:lamb.pickIf|pickIf}\n * @see {@link module:lamb.skipIn|skipIn}, {@link module:lamb.skip|skip},\n * {@link module:lamb.skipIf|skipIf}\n * @since 0.35.0\n * @param {String[]} whitelist\n * @returns {Function}\n */\nvar pick = _curry2(pickIn, true);\n\n/**\n * Builds a function expecting an object whose enumerable properties will be checked\n * against the given predicate.<br/>\n * The properties satisfying the predicate will be included in the resulting object.\n * @example\n * const user = {name: \"john\", surname: \"doe\", age: 30};\n * const 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.pickIn|pickIn}, {@link module:lamb.pick|pick}\n * @see {@link module:lamb.skipIn|skipIn}, {@link module:lamb.skip|skip},\n * {@link module:lamb.skipIf|skipIf}\n * @since 0.1.0\n * @param {ObjectIteratorCallback} predicate\n * @returns {Function}\n */\nfunction pickIf (predicate) {\n    return function (source) {\n        if (isNil(source)) {\n            throw _makeTypeErrorFor(source, \"object\");\n        }\n\n        var result = {};\n\n        for (var key in source) {\n            if (predicate(source[key], key, source)) {\n                result[key] = source[key];\n            }\n        }\n\n        return result;\n    };\n}\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 * const person = {\"firstName\": \"John\", \"lastName\": \"Doe\"};\n * const keysMap = {\"firstName\": \"name\", \"lastName\": \"surname\"};\n *\n * _.renameIn(person, keysMap) // => {\"name\": \"John\", \"surname\": \"Doe\"}\n *\n * @example <caption>It's safe using it to swap keys:</caption>\n * const keysMap = {\"firstName\": \"lastName\", \"lastName\": \"firstName\"};\n *\n * _.renameIn(person, keysMap) // => {\"lastName\": \"John\", \"firstName\": \"Doe\"}\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.rename|rename}, {@link module:lamb.renameWith|renameWith}\n * @since 0.26.0\n * @param {Object} source\n * @param {Object} keysMap\n * @returns {Object}\n */\nfunction renameIn (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.renameIn|renameIn} expecting a\n * <code>keysMap</code> to build a function waiting for the object to act upon.\n * @example\n * const persons = [\n *     {\"firstName\": \"John\", \"lastName\": \"Doe\"},\n *     {\"first_name\": \"Mario\", \"last_name\": \"Rossi\"},\n * ];\n * const normalizeKeys = _.rename({\n *     \"firstName\": \"name\",\n *     \"first_name\": \"name\",\n *     \"lastName\": \"surname\",\n *     \"last_name\": \"surname\"\n * });\n *\n * _.map(persons, normalizeKeys) // =>\n * // [\n * //     {\"name\": \"John\", \"surname\": \"Doe\"},\n * //     {\"name\": \"Mario\", \"surname\": \"Rossi\"}\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.renameIn|renameIn}, {@link module:lamb.renameWith|renameWith}\n * @since 0.26.0\n * @param {Object} keysMap\n * @returns {Function}\n */\nvar rename = _curry2(renameIn, true);\n\n/**\n * Uses the provided function as a <code>keysMap</code> generator and returns\n * a function expecting the object whose keys we want to {@link module:lamb.renameIn|renameIn}.\n * @example\n * const person = {\"NAME\": \"John\", \"SURNAME\": \"Doe\"};\n * const arrayToLower = _.mapWith(_.invoke(\"toLowerCase\"));\n * const makeLowerKeysMap = function (source) {\n *     const sourceKeys = _.keys(source);\n *\n *     return _.make(sourceKeys, arrayToLower(sourceKeys));\n * };\n * const lowerKeysFor = _.renameWith(makeLowerKeysMap);\n *\n * lowerKeysFor(person) // => {\"name\": \"John\", \"surname\": \"doe\"};\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.renameIn|renameIn}, {@link module:lamb.rename|rename}\n * @since 0.26.0\n * @param {Function} fn\n * @returns {Function}\n */\nfunction renameWith (fn) {\n    return function (source) {\n        return renameIn(source, fn(source));\n    };\n}\n\n/**\n * Sets, or creates, a property in a copy of the provided object to the desired value.\n * @private\n * @param {Object} source\n * @param {String} key\n * @param {*} value\n * @returns {Object}\n */\nfunction _setIn (source, key, value) {\n    var result = {};\n\n    for (var prop in source) {\n        result[prop] = source[prop];\n    }\n\n    result[key] = value;\n\n    return result;\n}\n\n/**\n * Sets the specified key to the given value in a copy of the provided object.<br/>\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.<br/>\n * If the specified key is not part of the source object, it will be added to the\n * result.<br/>\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).<br/>\n * For example the prototype of the result will be <code>Object</code>'s regardless\n * of the <code>source</code>'s one.\n * @example\n * const 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 * @since 0.18.0\n * @param {Object} source\n * @param {String} key\n * @param {*} value\n * @returns {Object}\n */\nfunction setIn (source, key, value) {\n    if (isNil(source)) {\n        throw _makeTypeErrorFor(source, \"object\");\n    }\n\n    return _setIn(source, key, value);\n}\n\n/**\n * Builds a partial application of {@link module:lamb.setIn|setIn} with the provided\n * <code>key</code> and <code>value</code>.<br/>\n * The resulting function expects the object to act upon.<br/>\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 * const user = {name: \"John\", surname: \"Doe\", age: 30};\n * const 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 * @function\n * @see {@link module:lamb.setIn|setIn}\n * @see {@link module:lamb.setPath|setPath}, {@link module:lamb.setPathIn|setPathIn}\n * @since 0.18.0\n * @param {String} key\n * @param {*} value\n * @returns {Function}\n */\nvar setKey = _makePartial3(setIn);\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 */\nfunction _isArrayIndex (target, key) {\n    var n = +key;\n\n    return Array.isArray(target) && n % 1 === 0 && !(n < 0 && _isEnumerable(target, key));\n}\n\n/**\n * Sets the object's property targeted by the given path to the desired value.<br/>\n * Works with arrays and is able to set their indexes, even negative ones.\n * @private\n * @param {Object|Array} source\n * @param {String[]} parts\n * @param {*} value\n * @returns {Object|Array}\n */\nfunction _setPathIn (source, parts, value) {\n    var key = parts[0];\n    var partsLen = parts.length;\n    var v;\n\n    if (partsLen === 1) {\n        v = value;\n    } else {\n        var targetKey = _getPathKey(source, key, false);\n\n        v = _setPathIn(\n            isUndefined(targetKey) ? targetKey : source[targetKey],\n            slice(parts, 1, partsLen),\n            value\n        );\n    }\n\n    return _isArrayIndex(source, key) ? _setIndex(source, key, v) : _setIn(source, key, v);\n}\n\n/**\n * Allows to change a nested value in a copy of the provided object.<br/>\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.<br/>\n * Note anyway that the distinction will be between <code>Array</code>s, 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}.<br/>\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.<br/>\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.<br/>\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.<br/>\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * const 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 <caption>Targeting arrays:</caption>\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 <caption>Arrays can also be part of the path and not necessarily its target:</caption>\n * const user = {\n *     id: 1,\n *     scores: [\n *         {value: 2, year: \"2000\"},\n *         {value: 4, year: \"2001\"},\n *         {value: 6, year: \"2002\"}\n *     ]\n * };\n *\n * const newUser = _.setPathIn(user, \"scores.0.value\", 8);\n * // \"newUser\" holds:\n * // {\n * //     id: 1,\n * //     scores: [\n * //         {value: 8, year: \"2000\"},\n * //         {value: 4, year: \"2001\"},\n * //         {value: 6, year: \"2002\"}\n * //     ]\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 * @since 0.20.0\n * @param {Object|Array} source\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Object|Array}\n */\nfunction 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 partial application of {@link module:lamb.setPathIn|setPathIn} expecting the\n * object to act upon.<br/>\n * See {@link module:lamb.setPathIn|setPathIn} for more details and examples.\n * @example\n * const user = {id: 1, status: {active: false}};\n * const 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 * @since 0.20.0\n * @param {String} path\n * @param {*} value\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\nfunction setPath (path, value, separator) {\n    return function (source) {\n        return setPathIn(source, path, value, separator);\n    };\n}\n\n/**\n * Returns a copy of the source object without the specified properties.\n * @example\n * const user = {name: \"john\", surname: \"doe\", age: 30};\n *\n * _.skipIn(user, [\"name\", \"age\"]) // => {surname: \"doe\"};\n * _.skipIn(user, [\"name\", \"email\"]) // => {surname: \"doe\", age: 30};\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.skip|skip}, {@link module:lamb.skipIf|skipIf}\n * @see {@link module:lamb.pickIn|pickIn}, {@link module:lamb.pick|pick},\n * {@link module:lamb.pickIf|pickIf}\n * @since 0.1.0\n * @param {Object} source\n * @param {String[]} blacklist\n * @returns {Object}\n */\nfunction skipIn (source, blacklist) {\n    if (isNil(source)) {\n        throw _makeTypeErrorFor(source, \"object\");\n    }\n\n    var result = {};\n    var props = make(blacklist, []);\n\n    for (var key in source) {\n        if (!(key in props)) {\n            result[key] = source[key];\n        }\n    }\n\n    return result;\n}\n\n/**\n * A curried version of {@link module:lamb.skipIn|skipIn}, expecting a blacklist of keys to build\n * a function waiting for the object to act upon.\n * @example\n * const user = {id: 1, name: \"Jane\", surname: \"Doe\", active: false};\n * const getUserInfo = _.skip([\"name\", \"surname\"]);\n *\n * getUserInfo(user) // => {id: 1, active: false}\n *\n * @example <caption>A useful composition with <code>mapWith</code>:</caption>\n * const 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 * const discard = _.compose(_.mapWith, _.skip);\n * const 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.skipIn|skipIn}, {@link module:lamb.skipIf|skipIf}\n * @see {@link module:lamb.pickIn|pickIn}, {@link module:lamb.pick|pick},\n * {@link module:lamb.pickIf|pickIf}\n * @since 0.35.0\n * @param {String[]} blacklist\n * @returns {Function}\n */\nvar skip = _curry2(skipIn, true);\n\n/**\n * Builds a function expecting an object whose enumerable properties will be checked\n * against the given predicate.<br/>\n * The properties satisfying the predicate will be omitted in the resulting object.\n * @example\n * const user = {name: \"john\", surname: \"doe\", age: 30};\n * const 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.skipIn|skipIn}, {@link module:lamb.skip|skip}\n * @see {@link module:lamb.pickIn|pickIn}, {@link module:lamb.pick|pick},\n * {@link module:lamb.pickIf|pickIf}\n * @since 0.1.0\n * @param {ObjectIteratorCallback} predicate\n * @returns {Function}\n */\nvar skipIf = compose(pickIf, not);\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 */\nvar _tearFrom = _curry2(function (getKeys, source) {\n    return reduce(getKeys(source), function (result, key) {\n        result[0].push(key);\n        result[1].push(source[key]);\n\n        return result;\n    }, [[], []]);\n});\n\n/**\n * Tears an object apart by transforming it in an array of two lists: one containing\n * its enumerable keys, the other containing the corresponding values.<br/>\n * Although this \"tearing apart\" may sound as a rather violent process, the source\n * object will be unharmed.\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 * @see {@link module:lamb.tearOwn|tearOwn}\n * @see {@link module:lamb.make|make} for the reverse operation\n * @since 0.8.0\n * @param {Object} source\n * @returns {Array<String[], Array>}\n */\nvar tear = _tearFrom(enumerables);\n\n/**\n * Same as {@link module:lamb.tear|tear}, but only the own properties of the object are\n * taken into account.\n * @example <caption>Showing the difference with <code>tear</code>:</caption>\n * const baseFoo = Object.create({a: 1}, {b: {value: 2, enumerable: true}, z: {value: 5}});\n * const 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 * @see {@link module:lamb.tear|tear}\n * @see {@link module:lamb.make|make} for the reverse operation\n * @since 0.12.0\n * @param {Object} source\n * @returns {Array<String[], Array>}\n */\nvar tearOwn = _tearFrom(keys);\n\n/**\n * Creates a copy of the given object having the desired key value updated by applying\n * the provided function to it.<br/>\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 * <code>source</code> is returned otherwise.\n * @example\n * const user = {name: \"John\", visits: 2};\n * const toUpperCase = _.invoke(\"toUpperCase\");\n *\n * _.updateIn(user, \"name\", toUpperCase) // => {name: \"JOHN\", visits: 2}\n * _.updateIn(user, \"surname\", toUpperCase) // => {name: \"John\", visits: 2}\n *\n * @example <caption>Non-enumerable properties will be treated as non-existent:</caption>\n * const user = Object.create({name: \"John\"}, {visits: {value: 2}});\n *\n * _.updateIn(user, \"visits\", _.add(1)) // => {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 * @since 0.22.0\n * @param {Object} source\n * @param {String} key\n * @param {Function} updater\n * @returns {Object}\n */\nfunction updateIn (source, key, updater) {\n    return _isEnumerable(source, key)\n        ? _setIn(source, key, updater(source[key]))\n        : _merge(enumerables, source, {});\n}\n\n/**\n * Builds a partial application of {@link module:lamb.updateIn|updateIn} with the provided\n * <code>key</code> and <code>updater</code>, expecting the object to act upon.<br/>\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 * <code>source</code> is returned otherwise.\n * @example\n * const user = {name: \"John\", visits: 2};\n * const incrementVisits = _.updateKey(\"visits\", _.add(1));\n *\n * incrementVisits(user) // => {name: \"John\", visits: 3}\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.updateIn|updateIn}\n * @see {@link module:lamb.updatePath|updatePath}, {@link module:lamb.updatePathIn|updatePathIn}\n * @since 0.22.0\n * @param {String} key\n * @param {Function} updater\n * @returns {Function}\n */\nvar updateKey = _makePartial3(updateIn);\n\n/**\n * Allows to change a nested value in a copy of the given object by applying the provided\n * function to it.<br/>\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 * <code>source</code> is returned otherwise.<br/>\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 * const user = {id: 1, status: {scores: [2, 4, 6], visits: 0}};\n * const inc = _.add(1);\n *\n * _.updatePathIn(user, \"status.visits\", inc) // => {id: 1, status: {scores: [2, 4, 6]}, visits: 1}\n *\n * @example <caption>Targeting arrays:</caption>\n * _.updatePathIn(user, \"status.scores.0\", inc) // => {id: 1, status: {scores: [3, 4, 6], visits: 0}}\n *\n * // you can use negative indexes as well\n * _.updatePathIn(user, \"status.scores.-1\", inc) // => {id: 1, status: {scores: [2, 4, 7], visits: 0}}\n *\n * @example <caption>Arrays can also be part of the path and not necessarily its target:</caption>\n * const user = {\n *     id: 1,\n *     scores: [\n *         {value: 2, year: \"2000\"},\n *         {value: 4, year: \"2001\"},\n *         {value: 6, year: \"2002\"}\n *     ]\n * };\n *\n * const newUser = _.updatePathIn(user, \"scores.0.value\", inc);\n * // \"newUser\" holds:\n * // {\n * //     id: 1,\n * //     scores: [\n * //         {value: 3, year: \"2000\"},\n * //         {value: 4, year: \"2001\"},\n * //         {value: 6, year: \"2002\"}\n * //     ]\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 * @since 0.24.0\n * @param {Object|Array} source\n * @param {String} path\n * @param {Function} updater\n * @param {String} [separator=\".\"]\n * @returns {Object|Array}\n */\nfunction 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, 0, source.length) : _merge(enumerables, source, {});\n    }\n}\n\n/**\n * Builds a partial application of {@link module:lamb.updatePathIn|updatePathIn}\n * expecting the object to act upon.<br/>\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 * <code>source</code> is returned otherwise.<br/>\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 * const user = {id: 1, status: {scores: [2, 4, 6], visits: 0}};\n * const incrementScores = _.updatePath(\"status.scores\", _.mapWith(_.add(1)))\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 * @since 0.24.0\n * @param {String} path\n * @param {Function} updater\n * @param {String} [separator=\".\"]\n * @returns {Function}\n */\nfunction updatePath (path, updater, separator) {\n    return function (source) {\n        return updatePathIn(source, path, updater, separator);\n    };\n}\n\n/**\n * Validates an object with the given list of {@link module:lamb.checker|checker} functions.\n * @example\n * const hasContent = s => s.trim().length > 0;\n * const userCheckers = [\n *     _.checker(hasContent, \"Name is required\", [\"name\"]),\n *     _.checker(hasContent, \"Surname is required\", [\"surname\"]),\n *     _.checker(_.isGTE(18), \"Must be at least 18 years old\", [\"age\"])\n * ];\n *\n * const user1 = {name: \"john\", surname: \"doe\", age: 30};\n * const user2 = {name: \"jane\", surname: \"\", age: 15};\n *\n * _.validate(user1, userCheckers) // => []\n * _.validate(user2, userCheckers) // =>\n * // [\n * //     [\"Surname is required\", [\"surname\"]],\n * //     [\"Must be at least 18 years old\", [\"age\"]]\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.validateWith|validateWith}\n * @see {@link module:lamb.checker|checker}\n * @since 0.1.0\n * @param {Object} source\n * @param {Function[]} checkers\n * @returns {Array<Array<String, String[]>>} An array of errors in the form returned by\n * {@link module:lamb.checker|checker}, or an empty array.\n */\nfunction validate (source, checkers) {\n    return reduce(checkers, function (errors, _checker) {\n        var result = _checker(source);\n\n        result.length && errors.push(result);\n\n        return errors;\n    }, []);\n}\n\n/**\n * A curried version of {@link module:lamb.validate|validate} accepting a list of\n * {@link module:lamb.checker|checkers} and returning a function expecting the object to validate.\n * @example\n * const hasContent = s => s.trim().length > 0;\n * const userCheckers = [\n *     _.checker(hasContent, \"Name is required\", [\"name\"]),\n *     _.checker(hasContent, \"Surname is required\", [\"surname\"]),\n *     _.checker(_.isGTE(18), \"Must be at least 18 years old\", [\"age\"])\n * ];\n * const validateUser = _.validateWith(userCheckers);\n *\n * const user1 = {name: \"john\", surname: \"doe\", age: 30};\n * const user2 = {name: \"jane\", surname: \"\", age: 15};\n *\n * validateUser(user1) // => []\n * validateUser(user2) // =>\n * // [\n * //     [\"Surname is required\", [\"surname\"]],\n * //     [\"Must be at least 18 years old\", [\"age\"]]\n * // ]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @see {@link module:lamb.validate|validate}\n * @see {@link module:lamb.checker|checker}\n * @since 0.1.0\n * @param {Function[]} checkers\n * @returns {Function}\n */\nvar validateWith = _curry2(validate, true);\n\n/**\n * Generates an array with the values of the enumerable properties of the given object.<br/>\n * See also {@link module:lamb.ownValues|ownValues} to pick only from the own properties of the object.\n * @example\n * const 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 * @see {@link module:lamb.ownValues|ownValues}\n * @since 0.1.0\n * @param {Object} source\n * @returns {Array}\n */\nvar values = _valuesFrom(enumerables);\n\n/**\n * A null-safe function to repeat the source string the desired amount of times.\n * @private\n * @param {String} source\n * @param {Number} times\n * @returns {String}\n */\nfunction _repeat (source, times) {\n    var result = \"\";\n\n    for (var i = 0; i < times; i++) {\n        result += source;\n    }\n\n    return result;\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 */\nfunction _getPadding (source, char, len) {\n    if (!isNil(source) && type(source) !== \"String\") {\n        source = String(source);\n    }\n\n    return _repeat(String(char)[0] || \"\", Math.ceil(len - source.length));\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 * @see {@link module:lamb.padRight|padRight}\n * @since 0.1.0\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 */\nfunction 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 * @see {@link module:lamb.padLeft|padLeft}\n * @since 0.1.0\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 */\nfunction 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.<br/>\n * Note that unlike the current ES6 proposal for\n * [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 <code>times</code> is negative,\n * 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 * @since 0.1.0\n * @param {String} source\n * @param {Number} times\n * @returns {String}\n */\nfunction repeat (source, times) {\n    if (isNil(source)) {\n        throw _makeTypeErrorFor(source, \"string\");\n    }\n\n    return _repeat(source, Math.floor(times));\n}\n\n/**\n * Builds a partial application of [<code>String.prototype.replace</code>]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace}\n * with the given needle and substitution.<br/>\n * Please refer to MDN docs for more insights and examples.\n * @example\n * const htmlString = \"<p>Lorem <strong class=\\\"foo bar\\\">ipsum dolor</strong> sit amet</p>\";\n * const stripHTML = _.replace(/<[^>]+>/g, \"\");\n *\n * stripHTML(htmlString) // => \"Lorem ipsum dolor sit amet\"\n *\n * @memberof module:lamb\n * @category String\n * @function\n * @see [<code>String.prototype.replace</code>]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace} on MDN.\n * @since 0.60.0\n * @param {RegExp|String} needle\n * @param {Function|String} sub\n * @returns {Function} <code>(haystack: String) => String</code>\n */\nvar replace = _makePartial3(generic(String.prototype.replace));\n\n/**\n * Splits a string into an array of substrings using the given separator.\n * @example\n * _.split(\"Jan,Feb,Mar,Apr,May\", \",\") // => [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\"]\n * _.split(\"Jan, Feb , Mar,Apr,   May\", /\\s*,\\s*‍/) // => [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\"]\n *\n * @memberof module:lamb\n * @category String\n * @function\n * @see {@link module:lamb.splitBy|splitBy}\n * @see {@link module:lamb.join|join}, {@link module:lamb.joinWith|joinWith}\n * @since 0.59.0\n * @param {String} source\n * @param {String|RegExp} separator\n * @returns {String[]}\n */\nvar split = binary(generic(String.prototype.split));\n\n/**\n * A curried version of {@link module:lamb.split|split} that accepts\n * a separator and builds a function expecting the string to split.\n * @example\n * const splitByCommma = _.splitBy(\",\");\n *\n * splitByCommma(\"Jan,Feb,Mar,Apr,May\") // => [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\"]\n *\n * @memberof module:lamb\n * @category String\n * @function\n * @see {@link module:lamb.split|split}\n * @see {@link module:lamb.join|join}, {@link module:lamb.joinWith|joinWith}\n * @since 0.59.0\n * @param {String|RegExp} separator\n * @returns {Function}\n */\nvar splitBy = _curry2(split, true);\n\n/**\n * A generic version of <code>String.prototype.search</code>\n * @private\n * @function\n * @param {String} s\n * @param {RegExp} pattern\n * @returns {Number}\n */\nvar _search = generic(String.prototype.search);\n\n/**\n * Builds a predicate expecting a string to test against the given regular expression pattern.\n * @example\n * const hasNumbersOnly = _.testWith(/^\\d+$/);\n *\n * hasNumbersOnly(\"123\") // => true\n * hasNumbersOnly(\"123 Kg\") // => false\n *\n * @memberof module:lamb\n * @category String\n * @since 0.1.0\n * @param {RegExp} pattern\n * @returns {Function}\n */\nfunction testWith (pattern) {\n    return function (s) {\n        return _search(s, pattern) !== -1;\n    };\n}\n\n/**\n * Accepts a constructor and builds a predicate expecting an object,\n * which will be tested to verify whether the prototype of the constructor\n * is in its prototype chain.<br/>\n * Wraps in a convenient way the native\n * [instanceof]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof} operator.\n * @example\n * function SomeObjA () {}\n *\n * const a = new SomeObjA();\n * const sObj = new String(\"foo\");\n * const s = \"foo\";\n *\n * _.isInstanceOf(Object)(a) // => true\n * _.isInstanceOf(SomeObjA)(a) // => true\n *\n * _.isInstanceOf(Object)(sObj) // => true\n * _.isInstanceOf(String)(sObj) // => true\n *\n * _.isInstanceOf(Object)(s) // => false\n * _.isInstanceOf(String)(s) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isType|isType}\n * @since 0.47.0\n * @param {*} constructor\n * @returns {Function}\n */\nfunction isInstanceOf (constructor) {\n    return function (obj) {\n        return obj instanceof constructor;\n    };\n}\n\n/**\n * Builds a predicate that expects a value to check against the specified type.\n * @example\n * const 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 * @since 0.1.0\n * @param {String} typeName\n * @returns {Function}\n */\nfunction isType (typeName) {\n    return function (value) {\n        return type(value) === typeName;\n    };\n}\n\nexport { __, adapter, add, allOf, always, anyOf, append, appendTo, application, apply, applyTo, areSVZ, areSame, aritize, asPartial, binary, casus, checker, clamp, clampWithin, collect, compose, condition, contains, count, countBy, curry, curryRight, curryable, curryableRight, debounce, deduct, difference, divide, divideBy, drop, dropFrom, dropLastWhile, dropWhile, enumerables, every, everyIn, filter, filterWith, find, findIndex, findIndexWhere, findLast, findLastIndex, findLastIndexWhere, findLastWhere, findWhere, flatMap, flatMapWith, flatten, flip, forEach, fromPairs, generate, generic, getArgAt, getAt, getIn, getIndex, getKey, getPath, getPathIn, group, groupBy, gt, gte, has, hasKey, hasKeyValue, hasOwn, hasOwnKey, hasPathValue, head, identity, index, indexBy, init, insert, insertAt, intersection, invoke, invokeOn, is, isFinite_ as isFinite, isGT, isGTE, isIn, isInstanceOf, isInteger, isLT, isLTE, isNil, isNull, isSVZ, isSafeInteger, isType, isUndefined, join, joinWith, keySatisfies, keys, last, list, lt, lte, make, map, mapArgs, mapValues, mapValuesWith, mapWith, mean, median, merge, mergeOwn, modulo, multiply, multiplyBy, not, ownPairs, ownValues, padLeft, padRight, pairs, partial, partialRight, partition, partitionWith, pathExists, pathExistsIn, pathSatisfies, pick, pickIf, pickIn, pipe, pluck, pluckFrom, pull, pullFrom, randomInt, range, reduce, reduceRight, reduceRightWith, reduceWith, remainder, rename, renameIn, renameWith, repeat, replace, reverse, rotate, rotateBy, setAt, setIn, setIndex, setKey, setPath, setPathIn, shallowFlatten, skip, skipIf, skipIn, slice, sliceAt, some, someIn, sort, sortWith, sortedInsert, sorter, sorterDesc, split, splitBy, subtract, sum, symmetricDifference, tail, take, takeFrom, takeLastWhile, takeWhile, tapArgs, tear, tearOwn, testWith, throttle, transpose, type, unary, union, unionBy, uniques, uniquesBy, unless, updateAt, updateIn, updateIndex, updateKey, updatePath, updatePathIn, validate, validateWith, values, when, zip, zipWithIndex };\n"]}