From 2542b9df58d34b0ea16ef1d7a64464bba9e28ae4 Mon Sep 17 00:00:00 2001 From: Andrea Scartabelli Date: Wed, 15 Nov 2023 09:10:59 +0100 Subject: [PATCH] Fixed `reduceWith` and `reduceRightWith` not using the initial value when `reduce` was called with more than three arguments --- dist/lamb.js | 8 ++++---- dist/lamb.min.js | 2 +- dist/lamb.min.js.map | 2 +- dist/lamb.min.mjs | 2 +- dist/lamb.min.mjs.map | 2 +- dist/lamb.mjs | 8 ++++---- src/array/__tests__/reduceRight.spec.js | 8 ++++++++ src/core/__tests__/reduce.spec.js | 8 ++++++++ src/privates/_makeReducer.js | 8 ++++---- 9 files changed, 32 insertions(+), 16 deletions(-) diff --git a/dist/lamb.js b/dist/lamb.js index b9942e2..4587cb6 100644 --- a/dist/lamb.js +++ b/dist/lamb.js @@ -580,10 +580,7 @@ var nCalls; var result; - if (arguments.length === 3) { - nCalls = len; - result = initialValue; - } else { + if (arguments.length < 3) { if (len === 0) { throw new TypeError("Reduce of empty array-like with no initial value"); } @@ -591,6 +588,9 @@ result = arrayLike[idx]; idx += step; nCalls = len - 1; + } else { + nCalls = len; + result = initialValue; } for (; nCalls--; idx += step) { diff --git a/dist/lamb.min.js b/dist/lamb.min.js index 74ed867..68d3441 100644 --- a/dist/lamb.min.js +++ b/dist/lamb.min.js @@ -5,5 +5,5 @@ * @module lamb * @license MIT */ -!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((n="undefined"!=typeof globalThis?globalThis:n||self).lamb={})}(this,(function(n){"use strict";var r={};function t(n,r){return n!=n?r!=r:n===r}function e(n){return function(r,t){return n.call(this,r,t)}}function u(n,r,t){return n=+n,(r=+r)>(t=+t)?NaN:nt?t:n}function i(n,t){return function(){if(!Array.isArray(t))return n.apply(this,arguments);for(var e,u=0,i=[],o=t.length,a=0;a>>0}function s(n,r){for(var t=0,e=h(n.length);te&&(i=e);for(var o=i-u,a=o>0?Array(o):[],f=0;f0&&t-1 in Object(r)?F(n):[]),i=e?new Set(u):null;this.add=function(n){return e?i.add(n):u.push(n),this},this.has=function(n){return e?i.has(n):M(u,n)}}function R(n,r){return new TypeError("Cannot convert "+S(n).toLowerCase()+" to "+r)}function K(n,r){for(var t=n.length,e=[],u=0;u=0&&e=0;a+=u)if(r(n[a],a,n)){o=a;break}return o}function $(n,r){return Y(n,r,!1)}function nn(n,r){var t=$(n,r);return-1===t?void 0:n[t]}var rn=d($,!0);function tn(n,r){return Y(n,r,!0)}function en(n,r){var t=tn(n,r);return-1===t?void 0:n[t]}var un=d(tn,!0),on=d(en,!0),an=d(nn,!0);function fn(n,r){return I(n,(function(n,t,e,u){var i=r(t,e,u);Array.isArray(i)||(i=[i]);for(var o=0,a=i.length,f=n.length;o=-r&&nr||n!=n?1:-1),e}function Jn(n,r,t){return"function"==typeof n&&n!==f||(n=null),"function"!=typeof t&&(t=Hn),{isDescending:!0===r,compare:function(r,e){return n&&(r=n(r),e=n(e)),t(r,e)}}}function Qn(n){return n&&"function"==typeof n.compare?n:Jn(n)}function Xn(n){return n&&n.length?A(n,Qn):[Jn()]}function Yn(n,r){for(var t=Xn(r),e=h(n.length),u=Array(e),i=0;i>1,o=t({value:r,index:i},{value:n[i],index:i});return u-e<=1?o<0?i:i+1:o<0?$n(n,r,t,e,i):0===o?i+1:$n(n,r,t,i,u)}var nr=i(Jn,[r,!1,r]),rr=i(Jn,[r,!0,r]),tr=d(Yn,!0);var er=G(1);function ur(n,r){return k(n,0,r)}var ir=d(ur,!0),or=Z(!0,!0),ar=Z(!0,!1);function fr(n){var r=l,t=h(n.length);if(0===t)return[];for(var e,u=0;u1&&e?o:1),f=Array(a),c=0;c=r?n.apply(this,t?f.reverse():f):mr(n,r,t,e,f)}}function Ar(n,r,t,e){return r>>>0!==r&&(r=n.length),e&&r>1||r>3?mr(n,r,t,e,[]):2===r?d(n,t):3===r?function(n,r){return function(t){return function(e){return function(u){return r?n.call(this,u,e,t):n.call(this,t,e,u)}}}}(n,t):n}function br(n,r,t){var e=t[n];if("function"==typeof e){for(var u=r?h(r.length):0,i=u+arguments.length-3,o=Array(i),a=0;ar}function Or(n,r){return n>=r}var Wr=d(xr),Sr=d(kr,!0),Nr=d(Or,!0);function Tr(n,r){return n=-u&&e>>0;if(0===t)return NaN;var e=A(n,Number).sort(Er);if(t%2==0){var u=t/2;r=(e[u-1]+e[u])/2}else r=e[(t-1)/2];return r},n.merge=lt,n.mergeOwn=ht,n.modulo=function(n,r){return n-r*Math.floor(n/r)},n.multiply=qr,n.multiplyBy=Cr,n.not=Lr,n.ownPairs=pt,n.ownValues=yt,n.padLeft=function(n,r,t){return Ct(n,r,t)+n},n.padRight=function(n,r,t){return n+Ct(n,r,t)},n.pairs=dt,n.partial=i,n.partialRight=function(n,t){return function(){if(!Array.isArray(t))return n.apply(this,arguments);for(var e,u=arguments.length-1,i=t.length,o=Array(i),a=[],f=i-1;f>-1;f--)e=t[f],o[f]=e===r?arguments[u--]:e;for(f=0;f<=u;f++)a[f]=arguments[f];for(var c=0;c=r&&(e=u,t=n.apply(this,arguments)),t}},n.transpose=fr,n.type=S,n.unary=function(n){return function(r){return n.call(this,r)}},n.union=hr,n.unionBy=lr,n.uniques=z,n.uniquesBy=D,n.unless=function(n,r){return function(t){return n.call(this,t)?t:r.call(this,t)}},n.updateAt=function(n,r){return function(t){return Dn(t,n,null,r)}},n.updateIn=Ft,n.updateIndex=sr,n.updateKey=Et,n.updatePath=function(n,r,t){return function(e){return Rt(e,n,r,t)}},n.updatePathIn=Rt,n.validate=Kt,n.validateWith=Dt,n.values=zt,n.when=function(n,r){return function(t){return n.call(this,t)?r.call(this,t):t}},n.zip=function(n,r){return fr([n,r])},n.zipWithIndex=vr})); +!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((n="undefined"!=typeof globalThis?globalThis:n||self).lamb={})}(this,(function(n){"use strict";var r={};function t(n,r){return n!=n?r!=r:n===r}function e(n){return function(r,t){return n.call(this,r,t)}}function u(n,r,t){return n=+n,(r=+r)>(t=+t)?NaN:nt?t:n}function i(n,t){return function(){if(!Array.isArray(t))return n.apply(this,arguments);for(var e,u=0,i=[],o=t.length,a=0;a>>0}function s(n,r){for(var t=0,e=h(n.length);te&&(i=e);for(var o=i-u,a=o>0?Array(o):[],f=0;f0&&t-1 in Object(r)?F(n):[]),i=e?new Set(u):null;this.add=function(n){return e?i.add(n):u.push(n),this},this.has=function(n){return e?i.has(n):M(u,n)}}function R(n,r){return new TypeError("Cannot convert "+S(n).toLowerCase()+" to "+r)}function K(n,r){for(var t=n.length,e=[],u=0;u=0&&e=0;a+=u)if(r(n[a],a,n)){o=a;break}return o}function $(n,r){return Y(n,r,!1)}function nn(n,r){var t=$(n,r);return-1===t?void 0:n[t]}var rn=d($,!0);function tn(n,r){return Y(n,r,!0)}function en(n,r){var t=tn(n,r);return-1===t?void 0:n[t]}var un=d(tn,!0),on=d(en,!0),an=d(nn,!0);function fn(n,r){return I(n,(function(n,t,e,u){var i=r(t,e,u);Array.isArray(i)||(i=[i]);for(var o=0,a=i.length,f=n.length;o=-r&&nr||n!=n?1:-1),e}function Jn(n,r,t){return"function"==typeof n&&n!==f||(n=null),"function"!=typeof t&&(t=Hn),{isDescending:!0===r,compare:function(r,e){return n&&(r=n(r),e=n(e)),t(r,e)}}}function Qn(n){return n&&"function"==typeof n.compare?n:Jn(n)}function Xn(n){return n&&n.length?A(n,Qn):[Jn()]}function Yn(n,r){for(var t=Xn(r),e=h(n.length),u=Array(e),i=0;i>1,o=t({value:r,index:i},{value:n[i],index:i});return u-e<=1?o<0?i:i+1:o<0?$n(n,r,t,e,i):0===o?i+1:$n(n,r,t,i,u)}var nr=i(Jn,[r,!1,r]),rr=i(Jn,[r,!0,r]),tr=d(Yn,!0);var er=G(1);function ur(n,r){return k(n,0,r)}var ir=d(ur,!0),or=Z(!0,!0),ar=Z(!0,!1);function fr(n){var r=l,t=h(n.length);if(0===t)return[];for(var e,u=0;u1&&e?o:1),f=Array(a),c=0;c=r?n.apply(this,t?f.reverse():f):mr(n,r,t,e,f)}}function Ar(n,r,t,e){return r>>>0!==r&&(r=n.length),e&&r>1||r>3?mr(n,r,t,e,[]):2===r?d(n,t):3===r?function(n,r){return function(t){return function(e){return function(u){return r?n.call(this,u,e,t):n.call(this,t,e,u)}}}}(n,t):n}function br(n,r,t){var e=t[n];if("function"==typeof e){for(var u=r?h(r.length):0,i=u+arguments.length-3,o=Array(i),a=0;ar}function Or(n,r){return n>=r}var Wr=d(xr),Sr=d(kr,!0),Nr=d(Or,!0);function Tr(n,r){return n=-u&&e>>0;if(0===t)return NaN;var e=A(n,Number).sort(Er);if(t%2==0){var u=t/2;r=(e[u-1]+e[u])/2}else r=e[(t-1)/2];return r},n.merge=lt,n.mergeOwn=ht,n.modulo=function(n,r){return n-r*Math.floor(n/r)},n.multiply=qr,n.multiplyBy=Cr,n.not=Lr,n.ownPairs=pt,n.ownValues=yt,n.padLeft=function(n,r,t){return Ct(n,r,t)+n},n.padRight=function(n,r,t){return n+Ct(n,r,t)},n.pairs=dt,n.partial=i,n.partialRight=function(n,t){return function(){if(!Array.isArray(t))return n.apply(this,arguments);for(var e,u=arguments.length-1,i=t.length,o=Array(i),a=[],f=i-1;f>-1;f--)e=t[f],o[f]=e===r?arguments[u--]:e;for(f=0;f<=u;f++)a[f]=arguments[f];for(var c=0;c=r&&(e=u,t=n.apply(this,arguments)),t}},n.transpose=fr,n.type=S,n.unary=function(n){return function(r){return n.call(this,r)}},n.union=hr,n.unionBy=lr,n.uniques=z,n.uniquesBy=D,n.unless=function(n,r){return function(t){return n.call(this,t)?t:r.call(this,t)}},n.updateAt=function(n,r){return function(t){return Dn(t,n,null,r)}},n.updateIn=Ft,n.updateIndex=sr,n.updateKey=Et,n.updatePath=function(n,r,t){return function(e){return Rt(e,n,r,t)}},n.updatePathIn=Rt,n.validate=Kt,n.validateWith=Dt,n.values=zt,n.when=function(n,r){return function(t){return n.call(this,t)?r.call(this,t):t}},n.zip=function(n,r){return fr([n,r])},n.zipWithIndex=vr})); //# sourceMappingURL=lamb.min.js.map diff --git a/dist/lamb.min.js.map b/dist/lamb.min.js.map index df6443f..c7a0b76 100644 --- a/dist/lamb.min.js.map +++ b/dist/lamb.min.js.map @@ -1 +1 @@ -{"version":3,"file":"lamb.min.js","names":["global","factory","exports","module","define","amd","globalThis","self","lamb","this","__","areSVZ","a","b","binary","fn","call","clamp","n","min","max","NaN","partial","args","Array","isArray","apply","arguments","boundArg","lastIdx","newArgs","argsLen","length","i","len","_makePartial3","shouldAritize","clampWithin","identity","value","compose","MAX_ARRAY_LENGTH","_toArrayLength","forEach","arrayLike","iteratee","generic","Function","bind","isNull","isUndefined","isNil","_curry2","isRightCurry","isSVZ","map","result","mapWith","_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","_LookupHelper","target","hasNativeSet","Set","sourceElements","sourceElementsSet","add","push","has","_makeTypeErrorFor","desiredType","toLowerCase","filter","predicate","uniquesBy","seen","uniques","difference","toExclude","v","dropFrom","drop","_takeOrDropWhile","isTake","fromLast","idxFrom","idxTo","lastHitIndex","increment","_getLastHitIndex","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","j","vLen","_makeArrayFlattener","flatten","_toNaturalIndex","getIndex","index","getAt","group","groupBy","head","indexBy","init","insert","splice","insertAt","join","separator","String","joinWith","last","list","partition","partitionWith","getIn","source","getKey","pluck","pullFrom","values","pull","reduceRight","reduceRightWith","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","sorter","sorterDesc","sortWith","tail","takeFrom","take","takeLastWhile","takeWhile","transpose","minLen","elementLen","pipe","functions","unionBy","union","updateIndex","zipWithIndex","application","applyTo","_asPartial","argsHolder","_currier","isAutoCurry","holderLen","newArgsLen","reverse","_curry","c","_curry3","_invoke","methodName","boundArgs","method","boundArgsLen","finalArgsLen","finalArgs","ofs","_checkPredicates","checkAll","predicates","allOf","anyOf","areSame","gt","gte","is","isGT","isGTE","lt","isLT","lte","isLTE","not","sum","subtract","deduct","divide","divideBy","isInteger","multiply","multiplyBy","_forceToNumber","_isOwnEnumerable","propertyIsEnumerable","_safeEnumerables","_isEnumerable","indexOf","_getPathKey","includeNonEnumerables","_getPathInfo","parts","walkNonEnumerables","isValid","_toPathParts","path","split","getPathIn","_unsafeKeyListFrom","getKeys","enumerables","getPath","hasKey","hasOwn","hasOwnProperty","hasOwnKey","keys","make","names","valuesLen","mapValues","mapValuesWith","_merge","merge","mergeOwn","_keyToPairIn","_pairsFrom","ownPairs","_valuesFrom","ownValues","pairs","pathExistsIn","pathExists","pickIn","whitelist","pick","pickIf","renameIn","keysMap","oldKeys","prop","rename","_setIn","setIn","setKey","_setPathIn","partsLen","targetKey","_isArrayIndex","setPathIn","skipIn","blacklist","props","skip","skipIf","_tearFrom","tear","tearOwn","updateIn","updateKey","updatePathIn","pathInfo","validate","checkers","errors","_checker","validateWith","_repeat","times","_getPadding","char","ceil","replace","splitBy","_search","search","adapter","always","asPartial","casus","checker","message","keyPaths","pathSeparator","obj","getValues","collect","condition","trueFn","falseFn","curry","curryRight","curryable","curryableRight","debounce","timespan","timeoutID","debounced","clearTimeout","setTimeout","flip","fromPairs","pairsList","pair","generate","limit","getArgAt","hasKeyValue","hasPathValue","intersection","resultLookup","bLookup","lenA","invoke","invokeOn","isFinite","isInstanceOf","constructor","isSafeInteger","isType","typeName","keySatisfies","mapArgs","mapper","mean","numbers","r","median","sortedNumbers","Number","modulo","padLeft","padRight","partialRight","pathSatisfies","pluckFrom","randomInt","random","range","remainder","renameWith","repeat","setPath","sortedInsert","symmetricDifference","tapArgs","tappers","tappersLen","testWith","pattern","s","throttle","lastCall","now","Date","unary","unless","updateAt","updatePath","when","zip"],"sources":["lamb.js"],"mappings":"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","sourcesContent":["/**\n* @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming.\n* @author Andrea Scartabelli \n* @version 0.61.1-beta.1\n* @module lamb\n* @license MIT\n*/\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.lamb = {}));\n})(this, (function (exports) { 'use strict';\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 */\n var __ = {};\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 */\n function 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.
\n * With this comparison NaN is equal to itself, but 0 and -0 are\n * considered the same value.
\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 */\n function 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.
\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 */\n function 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.
\n * The function will convert to number all its parameters before starting any\n * evaluation, and will return NaN if min is greater\n * than max.\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 */\n function 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.
\n * The {@link module:lamb.__|__} object can be used as a placeholder for arguments.
\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 */\n function 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.
\n * The shouldAritize parameter is for the \"reduce\" functions, where\n * the absence of the initialValue transforms a \"fold\" operation into a\n * \"reduce\" one.\n * @private\n * @param {Function} fn\n * @param {Boolean} shouldAritize\n * @returns {Function}\n */\n function _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 min\n * and a max 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 */\n var 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 */\n function 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 */\n function compose (a, b) {\n return arguments.length ? function () {\n return a.call(this, b.apply(this, arguments));\n } : identity;\n }\n\n var MAX_ARRAY_LENGTH = 4294967295;\n var MAX_SAFE_INTEGER = 9007199254740991;\n\n /**\n * Converts a value to a valid array length, thus an integer within\n * 0 and 232 - 1 (both included).\n * @private\n * @param {*} value\n * @returns {Number}\n */\n function _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 iteratee for each element of the given array-like object.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example Adding a CSS class to all elements of a NodeList in a browser environment:\n * 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 */\n function 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 */\n var generic = Function.bind.bind(Function.call);\n\n /**\n * Verifies if a value is null.\n * @example\n * _.isNull(null) // => true\n * _.isNull(void 0) // => false\n * _.isNull(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for undefined too.\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\n function isNull (value) {\n return value === null;\n }\n\n /**\n * Verifies if a value is undefined.\n * @example\n * _.isUndefined(null) // => false\n * _.isUndefined(void 0) // => true\n * _.isUndefined(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for null too.\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\n function isUndefined (value) {\n return value === void 0;\n }\n\n /**\n * Verifies if a value is null or undefined.\n * @example\n * _.isNil(NaN) // => false\n * _.isNil({}) // => false\n * _.isNil(null) // => true\n * _.isNil(void 0) // => true\n * _.isNil() // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNull|isNull}\n * @see {@link module:lamb.isUndefined|isUndefined}\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\n function 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 */\n function _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}.
\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.
\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 */\n var 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.
\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 */\n function 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 */\n var 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.
\n * The difference is that the bound arguments will be appended to the ones received by\n * the resulting function.\n * @example\n * Explaining the difference with partial:\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 * Explaining placeholder substitutions:\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 */\n function 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 step parameter must be 1\n * to build {@link module:lamb.reduce|reduce} and -1 to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\n function _makeReducer (step) {\n return function (arrayLike, accumulator, initialValue) {\n var len = _toArrayLength(arrayLike.length);\n var idx = step === 1 ? 0 : len - 1;\n var nCalls;\n var result;\n\n if (arguments.length === 3) {\n nCalls = len;\n result = initialValue;\n } else {\n if (len === 0) {\n throw new TypeError(\"Reduce of empty array-like with no initial value\");\n }\n\n result = arrayLike[idx];\n idx += step;\n nCalls = len - 1;\n }\n\n for (; nCalls--; idx += step) {\n result = accumulator(result, arrayLike[idx], idx, arrayLike);\n }\n\n return result;\n };\n }\n\n /**\n * Reduces (or folds) the values of an array-like object, starting from the first, to a new\n * value using the provided accumulator function.
\n * 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 */\n var reduce = _makeReducer(1);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduce} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * 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 */\n var reduceWith = _makePartial3(reduce, true);\n\n /**\n * Converts a value to an integer.\n * @private\n * @param {*} value\n * @returns {Number}\n */\n function _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.
\n * Note that unlike the native array method this function ensures that dense\n * arrays are returned.
\n * Also, unlike the native method, the start and end\n * parameters aren't optional and will be simply converted to integer.
\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 */\n function 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 start and end bounds, builds a partial application\n * of {@link module:lamb.slice|slice} expecting the array-like object to slice.
\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 */\n var sliceAt = _makePartial3(slice);\n\n var 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 */\n function 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 */\n function 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 */\n var append = _curry2(appendTo, true);\n\n /**\n * Checks if an array-like object contains the given value.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * 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 */\n function 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.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * 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 */\n var 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 */\n function _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 * iteratee, 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 */\n var 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 */\n var countBy = _curry2(count, true);\n\n var 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 */\n function _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 */\n function _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 */\n function _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 predicate\n * test.
\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 */\n function 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.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n function 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.
\n * Note that this function uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n var 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 */\n function 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 n elements of the given array or array-like object.\n * Note that, being this only a shortcut for a specific use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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 */\n function 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.
\n * See the note and examples for {@link module:lamb.dropFrom|dropFrom} about passing a\n * negative n.\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 */\n var 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 */\n function _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 */\n function _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 */\n var 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 */\n var 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 */\n function _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.
\n * The function will stop calling the predicate as soon as it returns a falsy value.
\n * Note that an empty array-like will always produce a true result regardless of the\n * predicate because of [vacuous truth]{@link https://en.wikipedia.org/wiki/Vacuous_truth}.
\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 Showing the difference with Array.prototype.every:\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 */\n var 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 */\n var 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 */\n var 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 */\n function _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 -1 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 */\n function 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 undefined 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 */\n function 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 */\n var 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 -1 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 */\n function 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 undefined 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 */\n function 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 */\n var 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 */\n var 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 */\n var 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 Showing the difference with map:\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 */\n function 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 */\n var 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 */\n function _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 */\n var _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 Showing the difference with shallowFlatten:\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 */\n var 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.
\n * Returns NaN otherwise.\n * @private\n * @param {Number} idx\n * @param {Number} len\n * @returns {Number}\n */\n function _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.
\n * Like {@link module:lamb.slice|slice} the index can be negative.
\n * If the index isn't supplied, or if its value isn't an integer within the array-like bounds,\n * the function will return undefined.
\n * getIndex will throw an exception when receives null or\n * undefined in place of an array-like object, but returns undefined\n * for any other value.\n * @example\n * 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 */\n function 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 Using negative indexes:\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 */\n var 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 Adding a custom value for missing keys:\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 */\n var 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 */\n var groupBy = _curry2(group, true);\n\n /**\n * Retrieves the first element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.head([1, 2, 3]) // => 1\n * _.head(\"hello\") // => \"h\"\n * _.head([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.last|last}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var 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.
\n * Should be used only when you're sure that your iteratee won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * 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 Result of an iteratee producing a duplicate key:\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 */\n var 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 */\n var 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 */\n var init = partial(slice, [__, 0, -1]);\n\n /**\n * Inserts the provided element in a copy of an array-like object at the\n * specified index.
\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.
\n * Negative indexes are allowed; when a negative index is out of bounds\n * the element will be inserted at the start of the resulting array.\n * @example\n * 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 */\n function 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 */\n var 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.
\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 */\n function 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.
\n * Note that unlike the native method, this function won't convert\n * null and undefined values in the array to empty\n * strings and that the separator parameter isn't optional.
\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 Showing the differences with the native array method:\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 */\n function 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.
\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 */\n var joinWith = _curry2(join, true);\n\n /**\n * Retrieves the last element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.last([1, 2, 3]) // => 3\n * _.last(\"hello\") // => \"o\"\n * _.last([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.head|head}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var 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.
\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 */\n function _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.
\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 */\n var 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}\n */\n function 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 */\n var 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 */\n function getIn (source, key) {\n return source[key];\n }\n\n /**\n * A curried version of {@link module:lamb.getIn|getIn}.
\n * Receives a property name and builds a function expecting the object from which we want to retrieve\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 */\n var 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 */\n var 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 */\n function 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.
\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 It's not the same as {@link module:lamb.difference|difference}:\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 */\n function 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.
\n * The new function will create an array copy of the array-like without\n * the specified values.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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 */\n var 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.
\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 */\n var reduceRight = _makeReducer(-1);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduceRight} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * 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 */\n var 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 */\n function 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 */\n function 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}.
\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 */\n var rotateBy = _curry2(rotate, true);\n\n /**\n * Sets an index in an array-like object.
\n * If provided with an updater function it will use it to update the current value,\n * otherwise sets the index to the specified value.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {Number} idx\n * @param {*} [value]\n * @param {Function} [updater]\n * @returns {Array}\n */\n function _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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 Using negative indexes:\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 */\n var setAt = _makePartial3(_setIndex);\n\n /**\n * Builds a new function that passes only the specified amount of arguments to the original one.
\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 Using a negative arity:\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 */\n function 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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 */\n var setIndex = aritize(_setIndex, 3);\n\n /**\n * Flattens the \"first level\" of an array.\n * @example Showing the difference with flatten:\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 */\n var shallowFlatten = _makeArrayFlattener(false);\n\n /**\n * Checks if at least one element in an array-like object satisfies the given predicate.
\n * The function will stop calling the predicate as soon as it returns a truthy value.
\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 Showing the difference with Array.prototype.some:\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 */\n var 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 */\n var 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 */\n function _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.
\n * If the given values are of different types they\n * will be both converted to strings.
\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\n function _comparer (a, b) {\n var result = 0;\n\n if (typeof a !== typeof b) {\n a = String(a);\n b = String(b);\n }\n\n if (!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 */\n function _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 */\n function _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 */\n function _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.
\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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used\n * in the comparison.
\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 Stable sort:\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 Stable multi-sort:\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 Using custom comparers:\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 */\n function 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 */\n function _getInsertionIndex (array, element, comparer, start, end) {\n if (array.length === 0) {\n return 0;\n }\n\n var pivot = (start + end) >> 1;\n var result = comparer(\n { value: element, 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 With simple values:\n * _.sortedInsert([], 1) // => [1]\n * _.sortedInsert([2, 4, 6], 5) // => [2, 4, 5, 6]\n * _.sortedInsert([4, 2, 1], 3, _.sorterDesc()) // => [4, 3, 2, 1]\n *\n * @example With complex values:\n * 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 */\n function 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 reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorterDesc|sorterDesc}\n * @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 */\n var sorter = partial(_sorter, [__, false, __]);\n\n /**\n * Creates a descending sort criterion with the provided reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}\n * @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 */\n var 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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in\n * the comparison.
\n * See {@link module:lamb.sort|sort} for more examples.\n *\n * @example\n * var sortAsNumbers = _.sortWith([parseFloat]);\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * sortAsNumbers(weights) // => [\"1 Kg\", \"2 Kg\", \"7 Kg\", \"10 Kg\"]\n *\n * @memberof module:lamb\n * @category Array\n * @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 */\n var 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}.
\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 */\n function 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 */\n var tail = drop(1);\n\n /**\n * Retrieves the first n elements from an array or array-like object.
\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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 */\n function 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.
\n * See the note and examples for {@link module:lamb.takeFrom|takeFrom} about passing a\n * negative n.\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 */\n var 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 */\n var 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 */\n var takeWhile = _takeOrDropWhile(true, false);\n\n /**\n * Transposes a matrix. Can also be used to reverse a {@link module:lamb.zip|zip} operation.
\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example Transposing a matrix:\n * _.transpose([\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ]) // =>\n * // [\n * // [1, 4, 7],\n * // [2, 5, 8],\n * // [3, 6, 9]\n * // ]\n *\n * @example Showing the relationship with zip:\n * 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\n * @returns {Array}\n */\n function 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 */\n function 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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n function 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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n var 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.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 */\n function updateAt (index, updater) {\n return function (arrayLike) {\n return _setIndex(arrayLike, index, null, updater);\n };\n }\n\n /**\n * Creates a copy of an array-like object with the given index changed by applying the\n * provided function to its value.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 */\n var 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.
\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}\n */\n function 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>}\n */\n var 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 */\n function 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 */\n var 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 */\n var 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.
\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 */\n function _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.
\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.
\n * The final application will happen when one of the generated functions is\n * invoked without placeholders, using the parameters collected so far.
\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 Explaining the function's behaviour:\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 Exploiting optional parameters:\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 */\n function 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 * collect.
\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 */\n function 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 */\n function _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 */\n function _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 _currier function.
\n * If the desumed arity isn't greater than one, it will return the received\n * function itself, instead.\n * @private\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @param {Boolean} [isRightCurry=false]\n * @param {Boolean} [isAutoCurry=false]\n * @returns {Function}\n */\n function _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.
\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 */\n function curry (fn, arity) {\n return _curry(fn, arity, false);\n }\n\n /**\n * Builds an auto-curried function. The resulting function can be called multiple times with\n * any number of arguments, and the original function will be applied only when the specified\n * (or derived) arity is consumed.
\n * Currying will start from the leftmost argument: use {@link module:lamb.curryableRight|curryableRight}\n * for right currying.\n * @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 */\n function curryable (fn, arity) {\n return _curry(fn, arity, false, true);\n }\n\n /**\n * Same as {@link module:lamb.curryable|curryable}, but currying starts from the rightmost argument.\n * @example\n * 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 */\n function curryableRight (fn, arity) {\n return _curry(fn, arity, true, true);\n }\n\n /**\n * Same as {@link module:lamb.curry|curry}, but currying starts from the rightmost argument.\n * @example\n * 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 */\n function curryRight (fn, arity) {\n return _curry(fn, arity, true);\n }\n\n /**\n * Returns a function that will execute the given function only if it stops being called for the\n * specified timespan.
\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call\n * happens immediately.\n * @example A common use case of debounce in a browser environment:\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 */\n function 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 */\n function 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.
\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.
\n * The resulting function will return undefined if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * 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 */\n function 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 undefined otherwise.
\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 args,\n * if present.\n * @private\n * @param {String} methodName\n * @param {Array} boundArgs\n * @param {Object} target\n * @param {...*} [args]\n * @returns {*}\n */\n function _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 * undefined.
\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.
\n * Returning undefined 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.
\n * See also {@link module:lamb.generic|generic} to create functions out of object methods.\n * @example Basic polymorphism with invoke:\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 With bound arguments:\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 */\n function 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 undefined.\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 */\n function 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 */\n function 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 */\n function 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.
\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 */\n function throttle (fn, timespan) {\n var result;\n var lastCall = 0;\n\n return function () {\n var now = Date.now();\n\n if (now - lastCall >= timespan) {\n lastCall = now;\n result = fn.apply(this, arguments);\n }\n\n return result;\n };\n }\n\n /**\n * Builds a function that passes only one argument to the given function.
\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.\n * @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 */\n function 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-undefined value.
\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 */\n function 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.
\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 */\n function _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 * false 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 */\n var 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 true 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 */\n var anyOf = _checkPredicates(false);\n\n /**\n * Verifies that the two supplied values are the same value using the \"SameValue\" comparison.
\n * Note that this doesn't behave as the strict equality operator, but rather as a shim of ES6's\n * [Object.is]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is}.\n * Differences are that 0 and -0 aren't the same value and, finally,\n * NaN is equal to itself.
\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 */\n function 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}.
\n * The function will apply the received arguments to fn if the predicate is satisfied\n * with the same arguments, otherwise will return undefined.
\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 */\n function 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 trueFn,\n * if the predicate is satisfied with the same arguments, or to falseFn otherwise.
\n * Although you can use other conditions as trueFn or falseFn,\n * it's probably better to use {@link module:lamb.adapter|adapter} to build more complex behaviours.
\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 */\n function 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.
\n * Wraps the native > 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 */\n function 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 * >= operator, so -0 === 0.\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 */\n function gte (a, b) {\n return a >= b;\n }\n\n /**\n * A curried version of {@link module:lamb.areSame|areSame}.
\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.
\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 */\n var is = _curry2(areSame);\n\n /**\n * A right curried version of {@link module:lamb.gt|gt}.
\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 */\n var isGT = _curry2(gt, true);\n\n /**\n * A right curried version of {@link module:lamb.gte|gte}.
\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 */\n var isGTE = _curry2(gte, true);\n\n /**\n * Verifies that the first given value is less than the second.
\n * Wraps the native < 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 */\n function lt (a, b) {\n return a < b;\n }\n\n /**\n * A right curried version of {@link module:lamb.lt|lt}.
\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 */\n var 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 * <= operator, so -0 === 0.\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 */\n function lte (a, b) {\n return a <= b;\n }\n\n /**\n * A right curried version of {@link module:lamb.lte|lte}.
\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 */\n var 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 */\n function 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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.when|when} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its trueFn 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 */\n function 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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.unless|unless} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its falseFn 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 */\n function 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 */\n function 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 */\n var 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 */\n function 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 */\n var 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 */\n function 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 */\n var 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 */\n function 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.
\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 true 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 */\n function 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 true 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 */\n function 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 -(253 - 1) inclusive to\n * 253 - 1 inclusive.
\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 true 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 */\n function 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 */\n function 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 */\n function 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 */\n function modulo (a, b) {\n return a - (b * Math.floor(a / b));\n }\n\n /**\n * Multiplies two numbers.\n * @example\n * _.multiply(5, 3) // => 15\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.multiplyBy|multiplyBy}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function multiply (a, b) {\n return a * b;\n }\n\n /**\n * 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 */\n var 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 randomInt(0.1, 1.2) could be 2.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @since 0.1.0\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n function randomInt (min, max) {\n return Math.floor(Math.random() * (max - min + 1) + min);\n }\n\n /**\n * 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 */\n function _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 start up to,\n * but not including, limit, using the given step.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(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 Behaviour if step happens to be zero:\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 */\n function 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 */\n function 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 */\n var _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 */\n function _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 */\n function _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 */\n function _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 */\n function _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 */\n function _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.
\n * The path is a string with property names separated by dots by default, but\n * it can be customised with the optional third parameter.
\n * You can use integers in the path, even negative ones, to refer to array-like\n * object indexes, but the priority will be given to existing object keys:\n * the last example explains this particular case.\n * @example\n * 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 Accessing array-like objects indexes:\n * _.getPathIn(user, \"login.password.1\") // => \"b\"\n * _.getPathIn(user, \"scores.0\") // => {id: 1, value: 10}\n * _.getPathIn(user, \"scores.-1.value\") // => 30\n *\n * @example Priority will be given to existing object keys over indexes:\n * _.getPathIn(user, \"scores.-1\") // => {id: 3, value: 30}\n *\n * // let's do something funny\n * user.scores[\"-1\"] = \"foo bar\";\n *\n * _.getPathIn(user, \"scores.-1\") // => \"foo bar\";\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPath|getPath}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @since 0.19.0\n * @param {Object|ArrayLike} source\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {*}\n */\n function getPathIn (source, path, separator) {\n return _getPathInfo(source, _toPathParts(path, separator), true).target;\n }\n\n /**\n * Builds a checker function meant to be used with\n * {@link module:lamb.validate|validate}.
\n * Note that the function accepts multiple keyPaths as a means to\n * compare their values. In other words all the received keyPaths will be\n * passed as arguments to the predicate to run the test.
\n * If you want to run the same single property check with multiple properties, you should build\n * multiple checkers and combine them with {@link module:lamb.validate|validate}.\n * @example\n * 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 * [\"message\", [\"propertyA\", \"propertyB\"]] or an empty array.\n */\n function checker (predicate, message, keyPaths, pathSeparator) {\n return function (obj) {\n var getValues = partial(getPathIn, [obj, __, pathSeparator]);\n\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 */\n var _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 Showing the difference with {@link module:lamb.keys|keys}:\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 */\n var 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}.
\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>} pairsList\n * @returns {Object}\n */\n function fromPairs (pairsList) {\n var result = {};\n\n forEach(pairsList, function (pair) {\n result[pair[0]] = pair[1];\n });\n\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.getPathIn|getPathIn} with the given\n * path and separator, expecting the object to act upon.
\n * @example\n * 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 */\n var 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 */\n function 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}.
\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 */\n var 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.
\n * @example Comparison with has:\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 */\n var hasOwn = generic(Object.prototype.hasOwnProperty);\n\n /**\n * Curried version of {@link module:lamb.hasOwn|hasOwn}.
\n * Returns a function expecting the object to check against the given key.\n * @example\n * 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 */\n var hasOwnKey = _curry2(hasOwn, true);\n\n /**\n * Builds a predicate expecting an object to check against the given key / value pair.
\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 */\n function 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.
\n * The value check is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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 */\n function 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 Object.keys.\n * @private\n * @function\n * @param {Object} source\n * @returns {String[]}\n */\n var _safeKeys = compose(Object.keys, Object);\n\n /**\n * Retrieves the list of the own enumerable properties of an object.
\n * Although [Object.keys]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys}\n * is already present in ECMAScript 5, its behaviour changed in the subsequent specifications\n * of the standard.
\n * This function shims the ECMAScript 6 version, by forcing a conversion to\n * object for any value but null and undefined.\n * @example Showing the difference with {@link module:lamb.enumerables|enumerables}:\n * 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 */\n var 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 */\n function 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.
\n * If the list of keys is longer than the values one, the keys will be created with\n * undefined values.
\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 */\n function 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 */\n function 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}.
\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 */\n var 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 */\n function _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.
\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.merge([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.merge(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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 */\n var 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 Showing the difference with merge:\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.mergeOwn([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.mergeOwn(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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 */\n var 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 */\n var _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 */\n var _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.
\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example Showing the difference with pairs:\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>}\n */\n var 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 */\n var _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.
\n * @example Showing the difference with values:\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 */\n var ownValues = _valuesFrom(keys);\n\n /**\n * Converts an object into an array of key / value pairs of its enumerable properties.
\n * See also {@link module:lamb.ownPairs|ownPairs} for picking only the own enumerable\n * properties and {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example\n * _.pairs({a: 1, b: 2, c: 3}) // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @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>}\n */\n var pairs = _pairsFrom(enumerables);\n\n /**\n * Checks if the provided path exists in the given object.
\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 */\n function 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.
\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 */\n var pathExists = _makePartial3(pathExistsIn);\n\n /**\n * Builds a predicate that verifies if a condition is satisfied for the given\n * path in an object.
\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 */\n function 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.
\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 */\n function 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 A useful composition with mapWith:\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 */\n var pick = _curry2(pickIn, true);\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked\n * against the given predicate.
\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 */\n function 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 It's safe using it to swap keys:\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 */\n function 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 * keysMap 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 */\n var rename = _curry2(renameIn, true);\n\n /**\n * Uses the provided function as a keysMap generator and returns\n * a function expecting the object whose keys we want to {@link module:lamb.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 */\n function 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 */\n function _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.
\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.
\n * If the specified key is not part of the source object, it will be added to the\n * result.
\n * The main purpose of the function is to work on simple plain objects used as\n * data structures, such as JSON objects, and makes no effort to play nice with\n * objects created from an OOP perspective (it's not worth it).
\n * For example the prototype of the result will be Object's regardless\n * of the source's one.\n * @example\n * 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 */\n function 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 * key and value.
\n * The resulting function expects the object to act upon.
\n * Please refer to {@link module:lamb.setIn|setIn}'s description for explanations about\n * how the copy of the source object is made.\n * @example\n * 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 */\n var 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 */\n function _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.
\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 */\n function _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.
\n * The function will delegate the \"set action\" to {@link module:lamb.setIn|setIn} or\n * {@link module:lamb.setAt|setAt} depending on the value encountered in the path,\n * so please refer to the documentation of those functions for specifics about the\n * implementation.
\n * Note anyway that the distinction will be between Arrays, delegated\n * to {@link module:lamb.setAt|setAt}, and everything else (including array-like objects),\n * which will be delegated to {@link module:lamb.setIn|setIn}.
\n * As a result of that, array-like objects will be converted to objects having numbers as keys\n * and paths targeting non-object values will be converted to empty objects.
\n * You can anyway target array elements using integers in the path, even negative ones, but\n * the priority will be given to existing, and enumerable, object keys.
\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.
\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * 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 Targeting arrays:\n * _.setPathIn(user, \"status.scores.0\", 8) // => {id: 1, status: {active : false, scores: [8, 4, 6]}}\n *\n * // you can use negative indexes as well\n * _.setPathIn(user, \"status.scores.-1\", 8) // => {id: 1, status: {active : false, scores: [2, 4, 8]}}\n *\n * @example Arrays can also be part of the path and not necessarily its target:\n * 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 */\n function setPathIn (source, path, value, separator) {\n if (isNil(source)) {\n throw _makeTypeErrorFor(source, \"object\");\n }\n\n return _setPathIn(source, _toPathParts(path, separator), value);\n }\n\n /**\n * Builds a partial application of {@link module:lamb.setPathIn|setPathIn} expecting the\n * object to act upon.
\n * See {@link module:lamb.setPathIn|setPathIn} for more details and examples.\n * @example\n * 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 */\n function 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 */\n function 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 A useful composition with mapWith:\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 */\n var skip = _curry2(skipIn, true);\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked\n * against the given predicate.
\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 */\n var 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 */\n var _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.
\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}\n */\n var tear = _tearFrom(enumerables);\n\n /**\n * Same as {@link module:lamb.tear|tear}, but only the own properties of the object are\n * taken into account.\n * @example Showing the difference with tear:\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}\n */\n var 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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 Non-enumerable properties will be treated as non-existent:\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 */\n function 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 * key and updater, expecting the object to act upon.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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 */\n var 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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 Targeting arrays:\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 Arrays can also be part of the path and not necessarily its target:\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 */\n function updatePathIn (source, path, updater, separator) {\n var parts = _toPathParts(path, separator);\n var pathInfo = _getPathInfo(source, parts, false);\n\n if (pathInfo.isValid) {\n return _setPathIn(source, parts, updater(pathInfo.target));\n } else {\n return Array.isArray(source) ? slice(source, 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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 */\n function 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>} An array of errors in the form returned by\n * {@link module:lamb.checker|checker}, or an empty array.\n */\n function 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 */\n var validateWith = _curry2(validate, true);\n\n /**\n * Generates an array with the values of the enumerable properties of the given object.
\n * See also {@link module:lamb.ownValues|ownValues} 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 */\n var 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 */\n function _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 */\n function _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 */\n function padLeft (source, char, len) {\n return _getPadding(source, char, len) + source;\n }\n\n /**\n * Pads a string to the desired length with the given char starting from the end of the string.\n * @example\n * _.padRight(\"foo\", \"-\", 0) // => \"foo\"\n * _.padRight(\"foo\", \"-\", -1) // => \"foo\"\n * _.padRight(\"foo\", \"-\", 5) // => \"foo--\"\n * _.padRight(\"foo\", \"-\", 3) // => \"foo\"\n * _.padRight(\"foo\", \"ab\", 7) // => \"fooaaaa\"\n * _.padRight(\"foo\", \"\", 5) // => \"foo\"\n * _.padRight(\"\", \"-\", 5) // => \"-----\"\n *\n * @memberof module:lamb\n * @category String\n * @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 */\n function padRight (source, char, len) {\n return source + _getPadding(source, char, len);\n }\n\n /**\n * Builds a new string by repeating the source string the desired amount of times.
\n * Note that unlike the current ES6 proposal for\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 times 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 */\n function 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 [String.prototype.replace]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace}\n * with the given needle and substitution.
\n * Please refer to MDN docs for more insights and examples.\n * @example\n * const htmlString = \"

Lorem ipsum dolor sit amet

\";\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 [String.prototype.replace]{@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} (haystack: String) => String\n */\n var 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 */\n var 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 */\n var splitBy = _curry2(split, true);\n\n /**\n * A generic version of String.prototype.search\n * @private\n * @function\n * @param {String} s\n * @param {RegExp} pattern\n * @returns {Number}\n */\n var _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 */\n function 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.
\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 */\n function 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 */\n function isType (typeName) {\n return function (value) {\n return type(value) === typeName;\n };\n }\n\n exports.__ = __;\n exports.adapter = adapter;\n exports.add = add;\n exports.allOf = allOf;\n exports.always = always;\n exports.anyOf = anyOf;\n exports.append = append;\n exports.appendTo = appendTo;\n exports.application = application;\n exports.apply = apply;\n exports.applyTo = applyTo;\n exports.areSVZ = areSVZ;\n exports.areSame = areSame;\n exports.aritize = aritize;\n exports.asPartial = asPartial;\n exports.binary = binary;\n exports.casus = casus;\n exports.checker = checker;\n exports.clamp = clamp;\n exports.clampWithin = clampWithin;\n exports.collect = collect;\n exports.compose = compose;\n exports.condition = condition;\n exports.contains = contains;\n exports.count = count;\n exports.countBy = countBy;\n exports.curry = curry;\n exports.curryRight = curryRight;\n exports.curryable = curryable;\n exports.curryableRight = curryableRight;\n exports.debounce = debounce;\n exports.deduct = deduct;\n exports.difference = difference;\n exports.divide = divide;\n exports.divideBy = divideBy;\n exports.drop = drop;\n exports.dropFrom = dropFrom;\n exports.dropLastWhile = dropLastWhile;\n exports.dropWhile = dropWhile;\n exports.enumerables = enumerables;\n exports.every = every;\n exports.everyIn = everyIn;\n exports.filter = filter;\n exports.filterWith = filterWith;\n exports.find = find;\n exports.findIndex = findIndex;\n exports.findIndexWhere = findIndexWhere;\n exports.findLast = findLast;\n exports.findLastIndex = findLastIndex;\n exports.findLastIndexWhere = findLastIndexWhere;\n exports.findLastWhere = findLastWhere;\n exports.findWhere = findWhere;\n exports.flatMap = flatMap;\n exports.flatMapWith = flatMapWith;\n exports.flatten = flatten;\n exports.flip = flip;\n exports.forEach = forEach;\n exports.fromPairs = fromPairs;\n exports.generate = generate;\n exports.generic = generic;\n exports.getArgAt = getArgAt;\n exports.getAt = getAt;\n exports.getIn = getIn;\n exports.getIndex = getIndex;\n exports.getKey = getKey;\n exports.getPath = getPath;\n exports.getPathIn = getPathIn;\n exports.group = group;\n exports.groupBy = groupBy;\n exports.gt = gt;\n exports.gte = gte;\n exports.has = has;\n exports.hasKey = hasKey;\n exports.hasKeyValue = hasKeyValue;\n exports.hasOwn = hasOwn;\n exports.hasOwnKey = hasOwnKey;\n exports.hasPathValue = hasPathValue;\n exports.head = head;\n exports.identity = identity;\n exports.index = index;\n exports.indexBy = indexBy;\n exports.init = init;\n exports.insert = insert;\n exports.insertAt = insertAt;\n exports.intersection = intersection;\n exports.invoke = invoke;\n exports.invokeOn = invokeOn;\n exports.is = is;\n exports.isFinite = isFinite_;\n exports.isGT = isGT;\n exports.isGTE = isGTE;\n exports.isIn = isIn;\n exports.isInstanceOf = isInstanceOf;\n exports.isInteger = isInteger;\n exports.isLT = isLT;\n exports.isLTE = isLTE;\n exports.isNil = isNil;\n exports.isNull = isNull;\n exports.isSVZ = isSVZ;\n exports.isSafeInteger = isSafeInteger;\n exports.isType = isType;\n exports.isUndefined = isUndefined;\n exports.join = join;\n exports.joinWith = joinWith;\n exports.keySatisfies = keySatisfies;\n exports.keys = keys;\n exports.last = last;\n exports.list = list;\n exports.lt = lt;\n exports.lte = lte;\n exports.make = make;\n exports.map = map;\n exports.mapArgs = mapArgs;\n exports.mapValues = mapValues;\n exports.mapValuesWith = mapValuesWith;\n exports.mapWith = mapWith;\n exports.mean = mean;\n exports.median = median;\n exports.merge = merge;\n exports.mergeOwn = mergeOwn;\n exports.modulo = modulo;\n exports.multiply = multiply;\n exports.multiplyBy = multiplyBy;\n exports.not = not;\n exports.ownPairs = ownPairs;\n exports.ownValues = ownValues;\n exports.padLeft = padLeft;\n exports.padRight = padRight;\n exports.pairs = pairs;\n exports.partial = partial;\n exports.partialRight = partialRight;\n exports.partition = partition;\n exports.partitionWith = partitionWith;\n exports.pathExists = pathExists;\n exports.pathExistsIn = pathExistsIn;\n exports.pathSatisfies = pathSatisfies;\n exports.pick = pick;\n exports.pickIf = pickIf;\n exports.pickIn = pickIn;\n exports.pipe = pipe;\n exports.pluck = pluck;\n exports.pluckFrom = pluckFrom;\n exports.pull = pull;\n exports.pullFrom = pullFrom;\n exports.randomInt = randomInt;\n exports.range = range;\n exports.reduce = reduce;\n exports.reduceRight = reduceRight;\n exports.reduceRightWith = reduceRightWith;\n exports.reduceWith = reduceWith;\n exports.remainder = remainder;\n exports.rename = rename;\n exports.renameIn = renameIn;\n exports.renameWith = renameWith;\n exports.repeat = repeat;\n exports.replace = replace;\n exports.reverse = reverse;\n exports.rotate = rotate;\n exports.rotateBy = rotateBy;\n exports.setAt = setAt;\n exports.setIn = setIn;\n exports.setIndex = setIndex;\n exports.setKey = setKey;\n exports.setPath = setPath;\n exports.setPathIn = setPathIn;\n exports.shallowFlatten = shallowFlatten;\n exports.skip = skip;\n exports.skipIf = skipIf;\n exports.skipIn = skipIn;\n exports.slice = slice;\n exports.sliceAt = sliceAt;\n exports.some = some;\n exports.someIn = someIn;\n exports.sort = sort;\n exports.sortWith = sortWith;\n exports.sortedInsert = sortedInsert;\n exports.sorter = sorter;\n exports.sorterDesc = sorterDesc;\n exports.split = split;\n exports.splitBy = splitBy;\n exports.subtract = subtract;\n exports.sum = sum;\n exports.symmetricDifference = symmetricDifference;\n exports.tail = tail;\n exports.take = take;\n exports.takeFrom = takeFrom;\n exports.takeLastWhile = takeLastWhile;\n exports.takeWhile = takeWhile;\n exports.tapArgs = tapArgs;\n exports.tear = tear;\n exports.tearOwn = tearOwn;\n exports.testWith = testWith;\n exports.throttle = throttle;\n exports.transpose = transpose;\n exports.type = type;\n exports.unary = unary;\n exports.union = union;\n exports.unionBy = unionBy;\n exports.uniques = uniques;\n exports.uniquesBy = uniquesBy;\n exports.unless = unless;\n exports.updateAt = updateAt;\n exports.updateIn = updateIn;\n exports.updateIndex = updateIndex;\n exports.updateKey = updateKey;\n exports.updatePath = updatePath;\n exports.updatePathIn = updatePathIn;\n exports.validate = validate;\n exports.validateWith = validateWith;\n exports.values = values;\n exports.when = when;\n exports.zip = zip;\n exports.zipWithIndex = zipWithIndex;\n\n}));\n"]} \ No newline at end of file +{"version":3,"file":"lamb.min.js","names":["global","factory","exports","module","define","amd","globalThis","self","lamb","this","__","areSVZ","a","b","binary","fn","call","clamp","n","min","max","NaN","partial","args","Array","isArray","apply","arguments","boundArg","lastIdx","newArgs","argsLen","length","i","len","_makePartial3","shouldAritize","clampWithin","identity","value","compose","MAX_ARRAY_LENGTH","_toArrayLength","forEach","arrayLike","iteratee","generic","Function","bind","isNull","isUndefined","isNil","_curry2","isRightCurry","isSVZ","map","result","mapWith","_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","_LookupHelper","target","hasNativeSet","Set","sourceElements","sourceElementsSet","add","push","has","_makeTypeErrorFor","desiredType","toLowerCase","filter","predicate","uniquesBy","seen","uniques","difference","toExclude","v","dropFrom","drop","_takeOrDropWhile","isTake","fromLast","idxFrom","idxTo","lastHitIndex","increment","_getLastHitIndex","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","j","vLen","_makeArrayFlattener","flatten","_toNaturalIndex","getIndex","index","getAt","group","groupBy","head","indexBy","init","insert","splice","insertAt","join","separator","String","joinWith","last","list","partition","partitionWith","getIn","source","getKey","pluck","pullFrom","values","pull","reduceRight","reduceRightWith","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","sorter","sorterDesc","sortWith","tail","takeFrom","take","takeLastWhile","takeWhile","transpose","minLen","elementLen","pipe","functions","unionBy","union","updateIndex","zipWithIndex","application","applyTo","_asPartial","argsHolder","_currier","isAutoCurry","holderLen","newArgsLen","reverse","_curry","c","_curry3","_invoke","methodName","boundArgs","method","boundArgsLen","finalArgsLen","finalArgs","ofs","_checkPredicates","checkAll","predicates","allOf","anyOf","areSame","gt","gte","is","isGT","isGTE","lt","isLT","lte","isLTE","not","sum","subtract","deduct","divide","divideBy","isInteger","multiply","multiplyBy","_forceToNumber","_isOwnEnumerable","propertyIsEnumerable","_safeEnumerables","_isEnumerable","indexOf","_getPathKey","includeNonEnumerables","_getPathInfo","parts","walkNonEnumerables","isValid","_toPathParts","path","split","getPathIn","_unsafeKeyListFrom","getKeys","enumerables","getPath","hasKey","hasOwn","hasOwnProperty","hasOwnKey","keys","make","names","valuesLen","mapValues","mapValuesWith","_merge","merge","mergeOwn","_keyToPairIn","_pairsFrom","ownPairs","_valuesFrom","ownValues","pairs","pathExistsIn","pathExists","pickIn","whitelist","pick","pickIf","renameIn","keysMap","oldKeys","prop","rename","_setIn","setIn","setKey","_setPathIn","partsLen","targetKey","_isArrayIndex","setPathIn","skipIn","blacklist","props","skip","skipIf","_tearFrom","tear","tearOwn","updateIn","updateKey","updatePathIn","pathInfo","validate","checkers","errors","_checker","validateWith","_repeat","times","_getPadding","char","ceil","replace","splitBy","_search","search","adapter","always","asPartial","casus","checker","message","keyPaths","pathSeparator","obj","getValues","collect","condition","trueFn","falseFn","curry","curryRight","curryable","curryableRight","debounce","timespan","timeoutID","debounced","clearTimeout","setTimeout","flip","fromPairs","pairsList","pair","generate","limit","getArgAt","hasKeyValue","hasPathValue","intersection","resultLookup","bLookup","lenA","invoke","invokeOn","isFinite","isInstanceOf","constructor","isSafeInteger","isType","typeName","keySatisfies","mapArgs","mapper","mean","numbers","r","median","sortedNumbers","Number","modulo","padLeft","padRight","partialRight","pathSatisfies","pluckFrom","randomInt","random","range","remainder","renameWith","repeat","setPath","sortedInsert","symmetricDifference","tapArgs","tappers","tappersLen","testWith","pattern","s","throttle","lastCall","now","Date","unary","unless","updateAt","updatePath","when","zip"],"sources":["lamb.js"],"mappings":";;;;;;;CAOA,SAAWA,EAAQC,GACI,iBAAZC,SAA0C,oBAAXC,OAAyBF,EAAQC,SACrD,mBAAXE,QAAyBA,OAAOC,IAAMD,OAAO,CAAC,WAAYH,GACUA,GAA1ED,EAA+B,oBAAfM,WAA6BA,WAAaN,GAAUO,MAAqBC,KAAO,CAAC,EACrG,CAJD,CAIGC,MAAM,SAAWP,GAAW,aAY3B,IAAIQ,EAAK,CAAC,EA0DV,SAASC,EAAQC,EAAGC,GAChB,OAAOD,GAAMA,EAAIC,GAAMA,EAAID,IAAMC,CACrC,CAkBA,SAASC,EAAQC,GACb,OAAO,SAAUH,EAAGC,GAChB,OAAOE,EAAGC,KAAKP,KAAMG,EAAGC,EAC5B,CACJ,CAyBA,SAASI,EAAOC,EAAGC,EAAKC,GAKpB,OAJAF,GAAKA,GACLC,GAAOA,IACPC,GAAOA,GAGIC,IAEAH,EAAIC,EAAMA,EAAMD,EAAIE,EAAMA,EAAMF,CAE/C,CA+BA,SAASI,EAASP,EAAIQ,GAClB,OAAO,WACH,IAAKC,MAAMC,QAAQF,GACf,OAAOR,EAAGW,MAAMjB,KAAMkB,WAO1B,IAJA,IAIgBC,EAJZC,EAAU,EACVC,EAAU,GACVC,EAAUR,EAAKS,OAEVC,EAAI,EAAaA,EAAIF,EAASE,IACnCL,EAAWL,EAAKU,GAChBH,EAAQG,GAAKL,IAAalB,EAAKiB,UAAUE,KAAaD,EAG1D,IAAK,IAAIM,EAAMP,UAAUK,OAAQH,EAAUK,EAAKL,IAC5CC,EAAQG,KAAON,UAAUE,GAG7B,OAAOd,EAAGW,MAAMjB,KAAMqB,EAC1B,CACJ,CAaA,SAASK,EAAepB,EAAIqB,GACxB,OAAO,SAAUxB,EAAGC,GAGhB,OAAOS,EAFCc,GAAsC,IAArBT,UAAUK,OAAelB,EAAOC,GAAMA,EAE7C,CAACL,EAAIE,EAAGC,GAC9B,CACJ,CAuBA,IAAIwB,EAAcF,EAAclB,GAgBhC,SAASqB,EAAUC,GACf,OAAOA,CACX,CA0BA,SAASC,EAAS5B,EAAGC,GACjB,OAAOc,UAAUK,OAAS,WACtB,OAAOpB,EAAEI,KAAKP,KAAMI,EAAEa,MAAMjB,KAAMkB,WACtC,EAAIW,CACR,CAEA,IAAIG,EAAmB,WAUvB,SAASC,EAAgBH,GACrB,OAAOtB,EAAMsB,EAAO,EAAGE,KAAsB,CACjD,CAuBA,SAASE,EAASC,EAAWC,GACzB,IAAK,IAAIZ,EAAI,EAAGC,EAAMQ,EAAeE,EAAUZ,QAASC,EAAIC,EAAKD,IAC7DY,EAASD,EAAUX,GAAIA,EAAGW,EAElC,CAqBA,IAAIE,EAAUC,SAASC,KAAKA,KAAKD,SAAS/B,MAgB1C,SAASiC,EAAQV,GACb,OAAiB,OAAVA,CACX,CAgBA,SAASW,EAAaX,GAClB,YAAiB,IAAVA,CACX,CAmBA,SAASY,EAAOZ,GACZ,OAAOU,EAAOV,IAAUW,EAAYX,EACxC,CASA,SAASa,EAASrC,EAAIsC,GAClB,OAAO,SAAUzC,GACb,OAAO,SAAUC,GACb,OAAOwC,EAAetC,EAAGC,KAAKP,KAAMI,EAAGD,GAAKG,EAAGC,KAAKP,KAAMG,EAAGC,EACjE,CACJ,CACJ,CAsCA,IAAIyC,EAAQF,EAAQzC,GAoBpB,SAAS4C,EAAKX,EAAWC,GAIrB,IAHA,IAAIX,EAAMQ,EAAeE,EAAUZ,QAC/BwB,EAAShC,MAAMU,GAEVD,EAAI,EAAGA,EAAIC,EAAKD,IACrBuB,EAAOvB,GAAKY,EAASD,EAAUX,GAAIA,EAAGW,GAG1C,OAAOY,CACX,CAoBA,IAAIC,EAAUL,EAAQG,GAAK,GAwE3B,SAASG,EAAcC,GACnB,OAAO,SAAUf,EAAWgB,EAAaC,GACrC,IAEIC,EACAN,EAHAtB,EAAMQ,EAAeE,EAAUZ,QAC/B+B,EAAe,IAATJ,EAAa,EAAIzB,EAAM,EAIjC,GAAIP,UAAUK,OAAS,EAAG,CACtB,GAAY,IAARE,EACA,MAAM,IAAI8B,UAAU,oDAGxBR,EAASZ,EAAUmB,GACnBA,GAAOJ,EACPG,EAAS5B,EAAM,CACnB,MACI4B,EAAS5B,EACTsB,EAASK,EAGb,KAAOC,IAAUC,GAAOJ,EACpBH,EAASI,EAAYJ,EAAQZ,EAAUmB,GAAMA,EAAKnB,GAGtD,OAAOY,CACX,CACJ,CAoBA,IAAIS,EAASP,EAAa,GAuBtBQ,EAAa/B,EAAc8B,GAAQ,GAQvC,SAASE,EAAY5B,GACjB,IAAIrB,GAAKqB,EAET,OAAIrB,GAAMA,EACC,EACAA,EAAI,GAAM,EACVA,EAEAkD,KAAKC,MAAMD,KAAKE,IAAIpD,KAAOA,EAAI,GAAK,EAAI,EAEvD,CA2BA,SAASqD,EAAO3B,EAAW4B,EAAOC,GAC9B,IAAIvC,EAAMQ,EAAeE,EAAUZ,QAC/B0C,EAAQP,EAAWK,GACnBG,EAAOR,EAAWM,GAElBC,EAAQ,IACRA,EAAQA,GAASxC,EAAM,EAAIwC,EAAQxC,GAGnCyC,EAAO,EACPA,EAAOA,GAAQzC,EAAM,EAAIyC,EAAOzC,EACzByC,EAAOzC,IACdyC,EAAOzC,GAMX,IAHA,IAAI0C,EAAYD,EAAOD,EACnBlB,EAASoB,EAAY,EAAIpD,MAAMoD,GAAa,GAEvC3C,EAAI,EAAGA,EAAI2C,EAAW3C,IAC3BuB,EAAOvB,GAAKW,EAAU8B,EAAQzC,GAGlC,OAAOuB,CACX,CAyBA,IAAIqB,EAAU1C,EAAcoC,GAExBO,EAAsBC,OAAOC,UAAUC,SAuB3C,SAASC,EAAM3C,GACX,OAAOuC,EAAoB9D,KAAKuB,GAAOgC,MAAM,GAAI,EACrD,CAmBA,SAASY,EAAUvC,EAAWL,GAC1B,OAAOgC,EAAM3B,EAAW,EAAGA,EAAUZ,QAAQoD,OAAO,CAAC7C,GACzD,CAoBA,IAAI8C,EAASjC,EAAQ+B,GAAU,GAwB/B,SAASG,EAAM1C,EAAWL,GAGtB,IAFA,IAAIiB,GAAS,EAEJvB,EAAI,EAAGC,EAAMU,EAAUZ,OAAQC,EAAIC,EAAKD,IAC7C,GAAItB,EAAO4B,EAAOK,EAAUX,IAAK,CAC7BuB,GAAS,EACT,KACJ,CAGJ,OAAOA,CACX,CAoBA,IAAI+B,EAAWnC,EAAQkC,GAAM,GAQ7B,SAASE,EAAYC,GACjB,OAAO,SAAU7C,EAAWC,GAIxB,IAHA,IAGgB6C,EAASC,EAHrBnC,EAAS,CAAC,EACVtB,EAAMU,EAAUZ,OAEXC,EAAI,EAAiBA,EAAIC,EAAKD,IAGnCuB,EADAmC,EAAM9C,EADN6C,EAAU9C,EAAUX,GACIA,EAAGW,IACb6C,EAAUjC,EAAOmC,GAAMD,GAGzC,OAAOlC,CACX,CACJ,CA2BA,IAAIoC,EAAQJ,GAAW,SAAU5E,GAC7B,OAAOA,IAAMA,EAAI,CACrB,IA2BIiF,EAAUzC,EAAQwC,GAAO,GAEzBE,EAAchD,EAAQtB,MAAMwD,UAAUT,OA0B1C,SAASwB,EAAenD,GACpB,IAlBmBoD,EACf9D,EAiBA+D,EAA8B,mBAARC,IACtBC,EAAiB3E,MAAMC,QAAQmB,GAC7BA,GAnBFV,GADe8D,EAqBApD,GApBAoD,EAAOhE,OAASX,IAE5BG,MAAMC,QAAQuE,IAAmB,IAAR9D,GACb,iBAARA,GACAA,EAAM,GACLA,EAAM,KAAM6C,OAAOiB,GAgBrBF,EAAYlD,GACZ,IAGNwD,EAAoBH,EAAe,IAAIC,IAAIC,GAAkB,KAEjE1F,KAAK4F,IAAM,SAAU9D,GAOjB,OANI0D,EACAG,EAAkBC,IAAI9D,GAEtB4D,EAAeG,KAAK/D,GAGjB9B,IACX,EAEAA,KAAK8F,IAAM,SAAUhE,GACjB,OAAO0D,EACDG,EAAkBG,IAAIhE,GACtB+C,EAAKa,EAAgB5D,EAC/B,CACJ,CAUA,SAASiE,EAAmBjE,EAAOkE,GAC/B,OAAO,IAAIzC,UAAU,kBAAoBkB,EAAK3C,GAAOmE,cAAgB,OAASD,EAClF,CAsBA,SAASE,EAAQ/D,EAAWgE,GAIxB,IAHA,IAAI1E,EAAMU,EAAUZ,OAChBwB,EAAS,GAEJvB,EAAI,EAAGA,EAAIC,EAAKD,IACrB2E,EAAUhE,EAAUX,GAAIA,EAAGW,IAAcY,EAAO8C,KAAK1D,EAAUX,IAGnE,OAAOuB,CACX,CA8BA,SAASqD,EAAWhE,GAChB,OAAO,SAAUD,GAGb,IAFA,IAEoEL,EAFhEiB,EAAS,GAEJvB,EAAI,EAAGC,EAAMU,EAAUZ,OAAQ8E,EAAO,IAAIf,EAAwB9D,EAAIC,EAAKD,IAChFM,EAAQM,EAASD,EAAUX,GAAIA,EAAGW,GAE7BkE,EAAKP,IAAIhE,KACVuE,EAAKT,IAAI9D,GACTiB,EAAO8C,KAAK1D,EAAUX,KAI9B,OAAOuB,CACX,CACJ,CAqBA,IAAIuD,EAAUF,EAAUvE,GA0BxB,SAAS0E,EAAYpG,EAAGC,GACpB,GAAIsC,EAAMtC,GACN,MAAM2F,EAAkB3F,EAAG,SAG/B,IAAIoG,EAAY,IAAIlB,EAAclF,GAKlC,OAAOkG,EAAQJ,EAAO/F,GAJP,SAAUsG,GACrB,OAAQD,EAAUV,IAAIW,EAC1B,IAGJ,CAwBA,SAASC,EAAUvE,EAAW1B,GAC1B,OAAOqD,EAAM3B,EAAW1B,EAAG0B,EAAUZ,OACzC,CAuBA,IAAIoF,EAAOhE,EAAQ+D,GAAU,GAuC7B,SAASE,EAAkBC,EAAQC,GAC/B,OAAO,SAAUX,GACb,OAAO,SAAUhE,GACb,IAAI4E,EACAC,EACAC,EAlChB,SAA2B9E,EAAWgE,EAAWW,GAC7C,IAAIxD,EACA4D,EACAzF,EAAMU,EAAUZ,OAUpB,IARIuF,GACAxD,EAAM7B,EAAM,EACZyF,GAAa,IAEb5D,EAAM,EACN4D,EAAY,GAGT5D,GAAO,GAAKA,EAAM7B,GAAO0E,EAAUhE,EAAUmB,GAAMA,EAAKnB,IAC3DmB,GAAO4D,EAGX,OAAO5D,CACX,CAgB+B6D,CAAiBhF,EAAWgE,EAAWW,GAgB1D,OAdID,GAAUC,GACVC,EAAUE,EAAe,EACzBD,EAAQ7E,EAAUZ,QACXsF,GACPE,EAAU,EACVC,EAAQC,IACAJ,GAAUC,GAClBC,EAAU,EACVC,EAAQC,EAAe,IAEvBF,EAAUE,EACVD,EAAQ7E,EAAUZ,QAGfuC,EAAM3B,EAAW4E,EAASC,EACrC,CACJ,CACJ,CAuBA,IAAII,EAAgBR,GAAiB,GAAO,GAuBxCS,EAAYT,GAAiB,GAAO,GASxC,SAASU,EAAmBC,GACxB,OAAO,SAAUpF,EAAWgE,GACxB,IAAK,IAAI3E,EAAI,EAAGC,EAAMU,EAAUZ,OAAQC,EAAIC,EAAKD,IAC7C,GAAI+F,IAAkBpB,EAAUhE,EAAUX,GAAIA,EAAGW,GAC7C,OAAQoF,EAIhB,OAAOA,CACX,CACJ,CAyCA,IAAIC,EAAUF,GAAkB,GAuB5BG,EAAQ9E,EAAQ6E,GAAS,GAsBzBE,EAAa/E,EAAQuD,GAAQ,GAWjC,SAASyB,EAAYxF,EAAWgE,EAAWW,GACvC,IAAI/C,EACAmD,EACAzF,EAAMU,EAAUZ,OAChBwB,GAAU,EAEV+D,GACA/C,EAAQtC,EAAM,EACdyF,GAAa,IAEbnD,EAAQ,EACRmD,EAAY,GAGhB,IAAK,IAAI1F,EAAIuC,EAAOvC,EAAIC,GAAOD,GAAK,EAAGA,GAAK0F,EACxC,GAAIf,EAAUhE,EAAUX,GAAIA,EAAGW,GAAY,CACvCY,EAASvB,EACT,KACJ,CAGJ,OAAOuB,CACX,CA4BA,SAAS6E,EAAWzF,EAAWgE,GAC3B,OAAOwB,EAAWxF,EAAWgE,GAAW,EAC5C,CA4BA,SAAS0B,GAAM1F,EAAWgE,GACtB,IAAI7C,EAAMsE,EAAUzF,EAAWgE,GAE/B,OAAgB,IAAT7C,OAAa,EAASnB,EAAUmB,EAC3C,CAwBA,IAAIwE,GAAiBnF,EAAQiF,GAAW,GA2BxC,SAASG,GAAe5F,EAAWgE,GAC/B,OAAOwB,EAAWxF,EAAWgE,GAAW,EAC5C,CA4BA,SAAS6B,GAAU7F,EAAWgE,GAC1B,IAAI7C,EAAMyE,GAAc5F,EAAWgE,GAEnC,OAAgB,IAAT7C,OAAa,EAASnB,EAAUmB,EAC3C,CAuBA,IAAI2E,GAAqBtF,EAAQoF,IAAe,GAwB5CG,GAAgBvF,EAAQqF,IAAU,GAwBlCG,GAAYxF,EAAQkF,IAAM,GAqB9B,SAASO,GAASC,EAAOjG,GACrB,OAAOoB,EAAO6E,GAAO,SAAUtF,EAAQuF,EAAIhF,EAAKiF,GAC5C,IAAI9B,EAAIrE,EAASkG,EAAIhF,EAAKiF,GAErBxH,MAAMC,QAAQyF,KACfA,EAAI,CAACA,IAGT,IAAK,IAAIjF,EAAI,EAAGC,EAAMgF,EAAElF,OAAQiH,EAAOzF,EAAOxB,OAAQC,EAAIC,EAAKD,IAC3DuB,EAAOyF,EAAOhH,GAAKiF,EAAEjF,GAGzB,OAAOuB,CACX,GAAG,GACP,CAoBA,IAAI0F,GAAc9F,EAAQyF,IAAS,GAWnC,SAASM,GAAUL,EAAOM,EAAQC,EAAQtF,GACtC,IAAK,IAA+BxB,EAAO+G,EAAGC,EAArCtH,EAAI,EAAGC,EAAM4G,EAAM9G,OAAwBC,EAAIC,EAAKD,IAGzD,GAFAM,EAAQuG,EAAM7G,GAETT,MAAMC,QAAQc,GAEZ,GAAI6G,EACPD,GAAS5G,GAAO,EAAM8G,EAAQtF,GAC9BA,EAAMsF,EAAOrH,YAKb,IAHAuH,EAAOhH,EAAMP,OACbqH,EAAOrH,QAAUuH,EAEZD,EAAI,EAAGA,EAAIC,EAAMD,IAClBD,EAAOtF,KAASxB,EAAM+G,QAT1BD,EAAOtF,KAASxB,EAcxB,OAAO8G,CACX,CAUA,IAAIG,GAAsBpG,GAAQ,SAAUgG,EAAQN,GAChD,OAAOtH,MAAMC,QAAQqH,GAASK,GAASL,EAAOM,EAAQ,GAAI,GAAK7E,EAAMuE,EAAO,EAAGA,EAAM9G,OACzF,IAkBIyH,GAAUD,IAAoB,GAWlC,SAASE,GAAiB3F,EAAK7B,GAG3B,OAFA6B,EAAMI,EAAWJ,MAEF7B,GAAO6B,EAAM7B,EAAM6B,EAAM,EAAIA,EAAM7B,EAAM6B,EAAM1C,GAClE,CAyBA,SAASsI,GAAU/G,EAAWgH,GAC1B,IAAI7F,EAAM2F,GAAgBE,EAAOlH,EAAeE,EAAUZ,SAE1D,OAAO+B,GAAQA,EAAMnB,EAAUmB,QAAO,CAC1C,CA0BA,IAAI8F,GAAQzG,EAAQuG,IAAU,GA4D1BG,GAAQtE,GAAW,SAAU5E,EAAGC,GAChC,OAAKD,GAILA,EAAEA,EAAEoB,QAAUnB,EAEPD,GALI,CAACC,EAMhB,IAwCIkJ,GAAU3G,EAAQ0G,IAAO,GAmBzBE,GAAOH,GAAM,GAqDbD,GAAQpE,GAAW,SAAU5E,EAAGC,GAChC,OAAOA,CACX,IAgCIoJ,GAAU7G,EAAQwG,IAAO,GAkBzBM,GAAO5I,EAAQiD,EAAO,CAAC7D,EAAI,GAAI,IA4BnC,SAASyJ,GAAQvH,EAAWgH,EAAOlE,GAC/B,IAAIlC,EAASe,EAAM3B,EAAW,EAAGA,EAAUZ,QAI3C,OAFAwB,EAAO4G,OAAOR,EAAO,EAAGlE,GAEjBlC,CACX,CAwBA,IAAI6G,GAAWlI,EAAcgI,IA4E7B,SAASG,GAAM1H,EAAW2H,GACtB,OAAOhH,EAAIX,EAAW4H,QAAQF,KAAKE,OAAOD,GAC9C,CAsBA,IAAIE,GAAWrH,EAAQkH,IAAM,GAmBzBI,GAAOb,IAAO,GAuClB,IA3B2B9F,GA2BvB4G,IA3BuB5G,GA2BC,EA1BjB,WAKH,IAJA,IACI7B,GADUP,UAAUK,QAAU+B,IACdA,GAChBP,EAAShC,MAAMU,GAEVD,EAAI,EAAGA,EAAIC,EAAKD,IACrBuB,EAAOvB,GAAKN,UAAUM,EAAI8B,IAG9B,OAAOP,CACX,GAmCJ,SAASoH,GAAWhI,EAAWgE,GAI3B,IAHA,IAGgBmC,EAHZvF,EAAS,CAAC,GAAI,IACdtB,EAAMU,EAAUZ,OAEXC,EAAI,EAAOA,EAAIC,EAAKD,IAEzBuB,EAAOoD,EADPmC,EAAKnG,EAAUX,GACMA,EAAGW,GAAa,EAAI,GAAG0D,KAAKyC,GAGrD,OAAOvF,CACX,CAgCA,IAAIqH,GAAgBzH,EAAQwH,IAAW,GAmBvC,SAASE,GAAOC,EAAQpF,GACpB,OAAOoF,EAAOpF,EAClB,CAuBA,IAAIqF,GAAS5H,EAAQ0H,IAAO,GAwBxBG,GAAQzI,EAAQiB,EAASuH,IA2D7B,SAASE,GAAUtI,EAAWuI,GAC1B,OAAOA,EAASxE,EAAO/D,GAAW,SAAU8C,GACxC,OAAQJ,EAAK6F,EAAQzF,EACzB,IAAKnB,EAAM3B,EAAW,EAAGA,EAAUZ,OACvC,CA0BA,IAAIoJ,GAAOhI,EAAQ8H,IAAU,GAiBzBG,GAAc3H,GAAc,GAuB5B4H,GAAkBnJ,EAAckJ,IAAa,GA8CjD,SAASE,GAAQ3I,EAAW4I,GACxB,IAAItJ,EAAMU,EAAUZ,OAChByJ,EAAQD,EAAStJ,EAErB,OAAOqC,EAAM3B,GAAY6I,EAAOvJ,GAAKkD,OAAOb,EAAM3B,EAAW,GAAI6I,GACrE,CAmBA,IAAIC,GAAWtI,EAAQmI,IAAQ,GAa/B,SAASI,GAAW/I,EAAWmB,EAAKxB,EAAOqJ,GACvC,IAAIpI,EAASe,EAAM3B,EAAW,EAAGA,EAAUZ,QACvCd,EAAIwI,GAAgB3F,EAAKP,EAAOxB,QAMpC,OAJId,GAAMA,IACNsC,EAAOtC,GAA0B,IAArBS,UAAUK,OAAe4J,EAAQhJ,EAAU1B,IAAMqB,GAG1DiB,CACX,CA6BA,IAAIqI,GAAQ1J,EAAcwJ,IAqB1B,SAASG,GAAS/K,EAAIgL,GAClB,OAAO,WAIH,IAHA,IAAI7K,EAAIiD,EAAW4H,GACfxK,EAAOoJ,GAAKjJ,MAAM,KAAMC,WAAW4C,MAAM,EAAGrD,GAEvCe,EAAIV,EAAKS,OAAQC,EAAIf,EAAGe,IAC7BV,EAAKU,QAAK,EAGd,OAAOlB,EAAGW,MAAMjB,KAAMc,EAC1B,CACJ,CAyBA,IAAIyK,GAAWF,GAAQH,GAAW,GAkB9BM,GAAiBzC,IAAoB,GAsCrC0C,GAASnE,GAAkB,GAuB3BoE,GAAO/I,EAAQ8I,IAAQ,GAS3B,SAASE,GAAcC,GACnB,OAAO,SAAUzL,EAAGC,GAKhB,IAJA,IAAIqB,EAAMmK,EAASrK,OACfsK,EAAYD,EAAS,GACrB7I,EAAS8I,EAAUC,QAAQ3L,EAAE2B,MAAO1B,EAAE0B,OAEjCN,EAAI,EAAc,IAAXuB,GAAgBvB,EAAIC,EAAKD,IAErCuB,GADA8I,EAAYD,EAASpK,IACFsK,QAAQ3L,EAAE2B,MAAO1B,EAAE0B,OAO1C,OAJe,IAAXiB,IACAA,EAAS5C,EAAEgJ,MAAQ/I,EAAE+I,OAGlB0C,EAAUE,cAAgBhJ,EAASA,CAC9C,CACJ,CAYA,SAASiJ,GAAW7L,EAAGC,GACnB,IAAI2C,EAAS,EAYb,cAVW5C,UAAaC,IACpBD,EAAI4J,OAAO5J,GACXC,EAAI2J,OAAO3J,IAGVF,EAAOC,EAAGC,KAEX2C,EAAS5C,EAAIC,GAAKD,GAAMA,EAAI,GAAK,GAG9B4C,CACX,CAWA,SAASkJ,GAASC,EAAQH,EAAcI,GASpC,MARsB,mBAAXD,GAAyBA,IAAWrK,IAC3CqK,EAAS,MAGW,mBAAbC,IACPA,EAAWH,IAGR,CACHD,cAA+B,IAAjBA,EACdD,QAAS,SAAU3L,EAAGC,GAMlB,OALI8L,IACA/L,EAAI+L,EAAO/L,GACXC,EAAI8L,EAAO9L,IAGR+L,EAAShM,EAAGC,EACvB,EAER,CAQA,SAASgM,GAAgBP,GACrB,OAAOA,GAA0C,mBAAtBA,EAAUC,QAAyBD,EAAYI,GAAQJ,EACtF,CASA,SAASQ,GAAeC,GACpB,OAAOA,GAAWA,EAAQ/K,OAASuB,EAAIwJ,EAASF,IAAkB,CAACH,KACvE,CA+DA,SAASM,GAAMpK,EAAWmK,GAKtB,IAJA,IAAIV,EAAWS,GAAcC,GACzB7K,EAAMQ,EAAeE,EAAUZ,QAC/BwB,EAAShC,MAAMU,GAEVD,EAAI,EAAGA,EAAIC,EAAKD,IACrBuB,EAAOvB,GAAK,CAAEM,MAAOK,EAAUX,GAAI2H,MAAO3H,GAK9C,IAFAuB,EAAOwJ,KAAKZ,GAAaC,IAEpBpK,EAAI,EAAGA,EAAIC,EAAKD,IACjBuB,EAAOvB,GAAKuB,EAAOvB,GAAGM,MAG1B,OAAOiB,CACX,CAaA,SAASyJ,GAAoBnE,EAAOpD,EAASkH,EAAUpI,EAAOC,GAC1D,GAAqB,IAAjBqE,EAAM9G,OACN,OAAO,EAGX,IAAIkL,EAAS1I,EAAQC,GAAQ,EACzBjB,EAASoJ,EACT,CAAErK,MAAOmD,EAASkE,MAAOsD,GACzB,CAAE3K,MAAOuG,EAAMoE,GAAQtD,MAAOsD,IAGlC,OAAIzI,EAAMD,GAAS,EACRhB,EAAS,EAAI0J,EAAQA,EAAQ,EAC7B1J,EAAS,EACTyJ,GAAmBnE,EAAOpD,EAASkH,EAAUpI,EAAO0I,GACzC,IAAX1J,EACA0J,EAAQ,EAERD,GAAmBnE,EAAOpD,EAASkH,EAAUM,EAAOzI,EAEnE,CAiFA,IAAI0I,GAAS7L,EAAQoL,GAAS,CAAChM,GAAI,EAAOA,IAoBtC0M,GAAa9L,EAAQoL,GAAS,CAAChM,GAAI,EAAMA,IA0BzC2M,GAAWjK,EAAQ4J,IAAM,GA+C7B,IAAIM,GAAOlG,EAAK,GAwBhB,SAASmG,GAAU3K,EAAW1B,GAC1B,OAAOqD,EAAM3B,EAAW,EAAG1B,EAC/B,CAuBA,IAAIsM,GAAOpK,EAAQmK,IAAU,GAuBzBE,GAAgBpG,GAAiB,GAAM,GAuBvCqG,GAAYrG,GAAiB,GAAM,GA8BvC,SAASsG,GAAW/K,GAChB,IAAIgL,EAASnL,EACTP,EAAMQ,EAAeE,EAAUZ,QAEnC,GAAY,IAARE,EACA,MAAO,GAGX,IAAK,IAAW2L,EAAPvE,EAAI,EAAeA,EAAIpH,EAAKoH,KACjCuE,EAAanL,EAAeE,EAAU0G,GAAGtH,SAExB4L,IACbA,EAASC,GAMjB,IAFA,IAEgB9E,EAFZvF,EAAShC,MAAMoM,GAEV3L,EAAI,EAAOA,EAAI2L,EAAQ3L,IAG5B,IAFA8G,EAAKvF,EAAOvB,GAAKT,MAAMU,GAElBoH,EAAI,EAAGA,EAAIpH,EAAKoH,IACjBP,EAAGO,GAAK1G,EAAU0G,GAAGrH,GAI7B,OAAOuB,CACX,CAkBA,SAASsK,GAAMC,GACX,IAAKvM,MAAMC,QAAQsM,GACf,MAAMvH,EAAkBuH,EAAW,SAGvC,IAAI7L,EAAM6L,EAAU/L,OAEpB,OAAOE,EAAM,WAGT,IAFA,IAAIsB,EAASuK,EAAU,GAAGrM,MAAMjB,KAAMkB,WAE7BM,EAAI,EAAGA,EAAIC,EAAKD,IACrBuB,EAASuK,EAAU9L,GAAGjB,KAAKP,KAAM+C,GAGrC,OAAOA,CACX,EAAIlB,CACR,CAyBA,SAAS0L,GAASnL,GACd,OAAOiL,GAAK,CAAChN,EAAO6J,IAAOzB,GAAY9B,EAAK,IAAKP,EAAUhE,IAC/D,CA0BA,IAAIoL,GAAQD,GAAQ1L,GAsDpB,IAAI4L,GAAc5M,EAAQqK,GAAW,CAACjL,EAAIA,EAAI,KAAMA,IAwCpD,IAAIyN,GAAe1K,EAAQ3C,EAAO6J,KAelC,SAASyD,GAAarN,EAAIQ,GACtB,OAAOR,EAAGW,MAAMjB,KAAMsE,OAAOxD,GACjC,CAkBA,IAAIG,GAAQ0B,EAAQgL,IAoBhBC,GAAUjL,EAAQgL,IAAa,GAanC,SAASE,GAAYvN,EAAIwN,GACrB,OAAO,WAKH,IAJA,IAIyC3M,EAJrCG,EAAUJ,UAAUK,OACpBH,EAAU,EACVC,EAAU,GAELG,EAAI,EAAGC,EAAMqM,EAAWvM,OAAkBC,EAAIC,EAAKD,IACxDL,EAAW2M,EAAWtM,GACtBH,EAAQG,GAAKL,IAAalB,GAAMmB,EAAUE,EAAUJ,UAAUE,KAAaD,EAG/E,KAAOC,EAAUE,GACbD,EAAQG,KAAON,UAAUE,KAG7B,IAAKI,EAAI,EAAGA,EAAIF,EAASE,IACrB,GAAIN,UAAUM,KAAOvB,EACjB,OAAO4N,GAAWvN,EAAIe,GAI9B,IAAKG,EAAI,EAAGC,EAAMJ,EAAQE,OAAQC,EAAIC,EAAKD,IACnCH,EAAQG,KAAOvB,IACfoB,EAAQG,QAAK,GAIrB,OAAOlB,EAAGW,MAAMjB,KAAMqB,EAC1B,CACJ,CA8FA,SAAS0M,GAAUzN,EAAIgL,EAAO1I,EAAcoL,EAAaF,GACrD,OAAO,WAMH,IALA,IAAIG,EAAYH,EAAWvM,OACvBD,EAAUJ,UAAUK,OACpB2M,EAAaD,GAAa3M,EAAU,GAAK0M,EAAc1M,EAAU,GACjED,EAAUN,MAAMmN,GAEX1M,EAAI,EAAGA,EAAIyM,EAAWzM,IAC3BH,EAAQG,GAAKsM,EAAWtM,GAG5B,KAAOA,EAAI0M,EAAY1M,IACnBH,EAAQG,GAAKN,UAAUM,EAAIyM,GAG/B,OAAIC,GAAc5C,EACPhL,EAAGW,MAAMjB,KAAM4C,EAAevB,EAAQ8M,UAAY9M,GAElD0M,GAASzN,EAAIgL,EAAO1I,EAAcoL,EAAa3M,EAE9D,CACJ,CAgCA,SAAS+M,GAAQ9N,EAAIgL,EAAO1I,EAAcoL,GAKtC,OAJI1C,IAAU,IAAMA,IAChBA,EAAQhL,EAAGiB,QAGXyM,GAAe1C,EAAQ,GAAKA,EAAQ,EAC7ByC,GAASzN,EAAIgL,EAAO1I,EAAcoL,EAAa,IACrC,IAAV1C,EACA3I,EAAQrC,EAAIsC,GACF,IAAV0I,EAhCf,SAAkBhL,EAAIsC,GAClB,OAAO,SAAUzC,GACb,OAAO,SAAUC,GACb,OAAO,SAAUiO,GACb,OAAOzL,EAAetC,EAAGC,KAAKP,KAAMqO,EAAGjO,EAAGD,GAAKG,EAAGC,KAAKP,KAAMG,EAAGC,EAAGiO,EACvE,CACJ,CACJ,CACJ,CAyBeC,CAAQhO,EAAIsC,GAEZtC,CAEf,CAkNA,SAASiO,GAASC,EAAYC,EAAWlJ,GACrC,IAAImJ,EAASnJ,EAAOiJ,GAEpB,GAAsB,mBAAXE,EAAX,CAQA,IAJA,IAAIC,EAAeF,EAAYxM,EAAewM,EAAUlN,QAAU,EAC9DqN,EAAeD,EAAezN,UAAUK,OAAS,EACjDsN,EAAY9N,MAAM6N,GAEbpN,EAAI,EAAGA,EAAImN,EAAcnN,IAC9BqN,EAAUrN,GAAKiN,EAAUjN,GAG7B,IAAK,IAAIsN,EAAM,EAAItN,EAAGA,EAAIoN,EAAcpN,IACpCqN,EAAUrN,GAAKN,UAAUM,EAAIsN,GAGjC,OAAOJ,EAAOzN,MAAMsE,EAAQsJ,EAd5B,CAeJ,CAiPA,SAASE,GAAkBC,GACvB,OAAO,SAAUC,GACb,IAAKlO,MAAMC,QAAQiO,GACf,MAAMlJ,EAAkBkJ,EAAY,SAGxC,OAAO,WACH,IAAK,IAAoClM,EAAhCvB,EAAI,EAAGC,EAAMwN,EAAW1N,OAAgBC,EAAIC,EAAKD,IAAK,CAG3D,GAFAuB,EAASkM,EAAWzN,GAAGP,MAAMjB,KAAMkB,WAE/B8N,IAAajM,EACb,OAAO,EACJ,IAAKiM,GAAYjM,EACpB,OAAO,CAEf,CAEA,OAAOiM,CACX,CACJ,CACJ,CAsBA,IAAIE,GAAQH,IAAiB,GA2BzBI,GAAQJ,IAAiB,GA+B7B,SAASK,GAASjP,EAAGC,GACjB,OAAa,IAAND,GAAiB,IAANC,EAAU,EAAID,GAAM,EAAIC,EAAIF,EAAOC,EAAGC,EAC5D,CA4FA,SAASiP,GAAIlP,EAAGC,GACZ,OAAOD,EAAIC,CACf,CAwBA,SAASkP,GAAKnP,EAAGC,GACb,OAAOD,GAAKC,CAChB,CAsCA,IAAImP,GAAK5M,EAAQyM,IAwBbI,GAAO7M,EAAQ0M,IAAI,GAyBnBI,GAAQ9M,EAAQ2M,IAAK,GA8BzB,SAASI,GAAIvP,EAAGC,GACZ,OAAOD,EAAIC,CACf,CAwBA,IAAIuP,GAAOhN,EAAQ+M,IAAI,GAwBvB,SAASE,GAAKzP,EAAGC,GACb,OAAOD,GAAKC,CAChB,CAyBA,IAAIyP,GAAQlN,EAAQiN,IAAK,GAiBzB,SAASE,GAAK3J,GACV,OAAO,WACH,OAAQA,EAAUlF,MAAMjB,KAAMkB,UAClC,CACJ,CA6EA,SAAS6O,GAAK5P,EAAGC,GACb,OAAOD,EAAIC,CACf,CAkBA,IAAIwF,GAAMjD,EAAQoN,IAAK,GAevB,SAASC,GAAU7P,EAAGC,GAClB,OAAOD,EAAIC,CACf,CAmBA,IAAI6P,GAAStN,EAAQqN,IAAU,GAe/B,SAASE,GAAQ/P,EAAGC,GAChB,OAAOD,EAAIC,CACf,CAmBA,IAAI+P,GAAWxN,EAAQuN,IAAQ,GAwE/B,SAASE,GAAWtO,GAChB,MAAuB,WAAhB2C,EAAK3C,IAAuBA,EAAQ,GAAM,CACrD,CA4HA,SAASuO,GAAUlQ,EAAGC,GAClB,OAAOD,EAAIC,CACf,CAiBA,IAAIkQ,GAAa3N,EAAQ0N,IAAU,GA6BnC,SAASE,GAAgBzO,GACrB,IAAIrB,GAAKqB,EAET,OAAOrB,GAAMA,EAAIA,EAAI,CACzB,CA+EA,IAAI+P,GAAmBnO,EAAQiC,OAAOC,UAAUkM,sBAShD,SAASC,GAAkBpG,GACvB,IAAIvH,EAAS,GAEb,IAAK,IAAImC,KAAOoF,EACZvH,EAAO8C,KAAKX,GAGhB,OAAOnC,CACX,CASA,SAAS4N,GAAerG,EAAQpF,GAC5B,OAAOA,KAAOZ,OAAOgG,KAAYkG,GAAiBlG,EAAQpF,KAASwL,GAAiBpG,GAAQsG,QAAQ1L,GACxG,CAUA,SAAS2L,GAAatL,EAAQL,EAAK4L,GAC/B,GAAIA,GAAyB5L,KAAOZ,OAAOiB,IAAWoL,GAAcpL,EAAQL,GACxE,OAAOA,EAGX,IAAIzE,GAAKyE,EACLzD,EAAM8D,GAAUA,EAAOhE,OAE3B,OAAOd,IAAMgB,GAAOhB,EAAIgB,EAAMhB,EAAI,EAAIA,EAAIgB,EAAMhB,OAAI,CACxD,CAUA,SAASsQ,GAAczG,EAAQ0G,EAAOC,GAClC,GAAIvO,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAQpC,IALA,IAGIpF,EAHAK,EAAS+E,EACT9I,GAAK,EACLC,EAAMuP,EAAMzP,SAGPC,EAAIC,IAGLgB,EAFJyC,EAAM2L,GAAYtL,EAAQyL,EAAMxP,GAAIyP,KAMpC1L,EAASA,EAAOL,GAGpB,OAAO1D,IAAMC,EAAM,CAAEyP,SAAS,EAAM3L,OAAQA,GAAW,CAAE2L,SAAS,EAAO3L,YAAQ,EACrF,CAUA,SAAS4L,GAAcC,EAAMtH,GACzB,OAAOC,OAAOqH,GAAMC,MAAMvH,GAAa,IAC3C,CAqDA,SAASwH,GAAWhH,EAAQ8G,EAAMtH,GAC9B,OAAOiH,GAAazG,EAAQ6G,GAAaC,EAAMtH,IAAY,GAAMvE,MACrE,CA0DA,IAAIgM,GAAqB5O,GAAQ,SAAU6O,EAASlH,GAChD,GAAI5H,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,OAAOkH,EAAQlH,EACnB,IAsBImH,GAAcF,GAAmBb,IAyDrC,IAAIgB,GAAUhQ,EAAc4P,IA0B5B,SAASxL,GAAKwE,EAAQpF,GAKlB,MAJsB,iBAAXoF,GAAwB7H,EAAY6H,KAC3CA,EAAShG,OAAOgG,IAGbpF,KAAOoF,CAClB,CAuBA,IAAIqH,GAAShP,EAAQmD,IAAK,GA2BtB8L,GAASvP,EAAQiC,OAAOC,UAAUsN,gBAuBlCC,GAAYnP,EAAQiP,IAAQ,GA8EhC,IA2BIG,GAAOR,GA3BKxP,EAAQuC,OAAOyN,KAAMzN,SA4ErC,SAAS0N,GAAMC,EAAOvH,GAIlB,IAHA,IAAI3H,EAAS,CAAC,EACVmP,EAAYxH,EAAOnJ,OAEdC,EAAI,EAAGC,EAAMwQ,EAAM1Q,OAAQC,EAAIC,EAAKD,IACzCuB,EAAOkP,EAAMzQ,IAAMA,EAAI0Q,EAAYxH,EAAOlJ,QAAK,EAGnD,OAAOuB,CACX,CAqBA,SAASoP,GAAW7H,EAAQhK,GACxB,GAAIoC,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,IAAIvH,EAAS,CAAC,EAEd,IAAK,IAAImC,KAAOoF,EACZvH,EAAOmC,GAAO5E,EAAGgK,EAAOpF,GAAMA,EAAKoF,GAGvC,OAAOvH,CACX,CAwBA,IAAIqP,GAAgBzP,EAAQwP,IAAW,GAUvC,SAASE,GAAQb,EAASrR,EAAGC,GACzB,OAAOoD,EAAO,CAACrD,EAAGC,IAAI,SAAU2C,EAAQuH,GAKpC,OAJApI,EAAQsP,EAAQlH,IAAS,SAAUpF,GAC/BnC,EAAOmC,GAAOoF,EAAOpF,EACzB,IAEOnC,CACX,GAAG,CAAC,EACR,CAyBA,IAAIuP,GAAQzR,EAAQwR,GAAQ,CAACZ,KAiCzBc,GAAW1R,EAAQwR,GAAQ,CAACN,KAU5BS,GAAe7P,GAAQ,SAAU2H,EAAQpF,GACzC,MAAO,CAACA,EAAKoF,EAAOpF,GACxB,IAUIuN,GAAa9P,GAAQ,SAAU6O,EAASlH,GACxC,OAAOxH,EAAI0O,EAAQlH,GAASkI,GAAalI,GAC7C,IAwBIoI,GAAWD,GAAWV,IAUtBY,GAAchQ,GAAQ,SAAU6O,EAASlH,GACzC,OAAOxH,EAAI0O,EAAQlH,IAAS,SAAUpF,GAClC,OAAOoF,EAAOpF,EAClB,GACJ,IAsBI0N,GAAYD,GAAYZ,IAkBxBc,GAAQJ,GAAWhB,IA8BvB,SAASqB,GAAcxI,EAAQ8G,EAAMtH,GACjC,OAAOiH,GAAazG,EAAQ6G,GAAaC,EAAMtH,IAAY,GAAMoH,OACrE,CAmCA,IAAI6B,GAAarR,EAAcoR,IAyD/B,SAASE,GAAQ1I,EAAQ2I,GAGrB,IAFA,IAEwC/N,EAFpCnC,EAAS,CAAC,EAELvB,EAAI,EAAGC,EAAMwR,EAAU1R,OAAaC,EAAIC,EAAKD,IAG9CsE,GAAIwE,EAFRpF,EAAM+N,EAAUzR,MAGZuB,EAAOmC,GAAOoF,EAAOpF,IAI7B,OAAOnC,CACX,CAuCA,IAAImQ,GAAOvQ,EAAQqQ,IAAQ,GAqB3B,SAASG,GAAQhN,GACb,OAAO,SAAUmE,GACb,GAAI5H,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,IAAIvH,EAAS,CAAC,EAEd,IAAK,IAAImC,KAAOoF,EACRnE,EAAUmE,EAAOpF,GAAMA,EAAKoF,KAC5BvH,EAAOmC,GAAOoF,EAAOpF,IAI7B,OAAOnC,CACX,CACJ,CAwBA,SAASqQ,GAAU9I,EAAQ+I,GACvBA,EAAU/O,OAAO+O,GACjB,IAAItQ,EAAS,CAAC,EACVuQ,EAAU7B,GAAYnH,GAE1B,IAAK,IAAIiJ,KAAQF,GACRC,EAAQ1C,QAAQ2C,KACjBxQ,EAAOsQ,EAAQE,IAASjJ,EAAOiJ,IAIvC,IAAK,IAAiCrO,EAA7B1D,EAAI,EAAGC,EAAM6R,EAAQ/R,OAAaC,EAAIC,EAAKD,KAChD0D,EAAMoO,EAAQ9R,MAED6R,GAAWnO,KAAOnC,IAC3BA,EAAOmC,GAAOoF,EAAOpF,IAI7B,OAAOnC,CACX,CA+BA,IAAIyQ,GAAS7Q,EAAQyQ,IAAU,GAsC/B,SAASK,GAAQnJ,EAAQpF,EAAKpD,GAC1B,IAAIiB,EAAS,CAAC,EAEd,IAAK,IAAIwQ,KAAQjJ,EACbvH,EAAOwQ,GAAQjJ,EAAOiJ,GAK1B,OAFAxQ,EAAOmC,GAAOpD,EAEPiB,CACX,CA+BA,SAAS2Q,GAAOpJ,EAAQpF,EAAKpD,GACzB,GAAIY,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,OAAOmJ,GAAOnJ,EAAQpF,EAAKpD,EAC/B,CA0BA,IAAI6R,GAASjS,EAAcgS,IAyB3B,SAASE,GAAYtJ,EAAQ0G,EAAOlP,GAChC,IAEI2E,EAFAvB,EAAM8L,EAAM,GACZ6C,EAAW7C,EAAMzP,OAGrB,GAAiB,IAAbsS,EACApN,EAAI3E,MACD,CACH,IAAIgS,EAAYjD,GAAYvG,EAAQpF,GAAK,GAEzCuB,EAAImN,GACAnR,EAAYqR,GAAaA,EAAYxJ,EAAOwJ,GAC5ChQ,EAAMkN,EAAO,EAAG6C,GAChB/R,EAER,CAEA,OAhCJ,SAAwByD,EAAQL,GAC5B,IAAIzE,GAAKyE,EAET,OAAOnE,MAAMC,QAAQuE,IAAW9E,EAAI,GAAM,KAAOA,EAAI,GAAKkQ,GAAcpL,EAAQL,GACpF,CA4BW6O,CAAczJ,EAAQpF,GAAOgG,GAAUZ,EAAQpF,EAAKuB,GAAKgN,GAAOnJ,EAAQpF,EAAKuB,EACxF,CA6DA,SAASuN,GAAW1J,EAAQ8G,EAAMtP,EAAOgI,GACrC,GAAIpH,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,OAAOsJ,GAAWtJ,EAAQ6G,GAAaC,EAAMtH,GAAYhI,EAC7D,CA8CA,SAASmS,GAAQ3J,EAAQ4J,GACrB,GAAIxR,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,IAAIvH,EAAS,CAAC,EACVoR,EAAQnC,GAAKkC,EAAW,IAE5B,IAAK,IAAIhP,KAAOoF,EACNpF,KAAOiP,IACTpR,EAAOmC,GAAOoF,EAAOpF,IAI7B,OAAOnC,CACX,CAuCA,IAAIqR,GAAOzR,EAAQsR,IAAQ,GAsBvBI,GAAStS,EAAQoR,GAAQrD,IAYzBwE,GAAY3R,GAAQ,SAAU6O,EAASlH,GACvC,OAAO9G,EAAOgO,EAAQlH,IAAS,SAAUvH,EAAQmC,GAI7C,OAHAnC,EAAO,GAAG8C,KAAKX,GACfnC,EAAO,GAAG8C,KAAKyE,EAAOpF,IAEfnC,CACX,GAAG,CAAC,GAAI,IACZ,IAmBIwR,GAAOD,GAAU7C,IAuBjB+C,GAAUF,GAAUvC,IA8BxB,SAAS0C,GAAUnK,EAAQpF,EAAKiG,GAC5B,OAAOwF,GAAcrG,EAAQpF,GACvBuO,GAAOnJ,EAAQpF,EAAKiG,EAAQb,EAAOpF,KACnCmN,GAAOZ,GAAanH,EAAQ,CAAC,EACvC,CAwBA,IAAIoK,GAAYhT,EAAc+S,IAsD9B,SAASE,GAAcrK,EAAQ8G,EAAMjG,EAASrB,GAC1C,IAAIkH,EAAQG,GAAaC,EAAMtH,GAC3B8K,EAAW7D,GAAazG,EAAQ0G,GAAO,GAE3C,OAAI4D,EAAS1D,QACF0C,GAAWtJ,EAAQ0G,EAAO7F,EAAQyJ,EAASrP,SAE3CxE,MAAMC,QAAQsJ,GAAUxG,EAAMwG,EAAQ,EAAGA,EAAO/I,QAAU8Q,GAAOZ,GAAanH,EAAQ,CAAC,EAEtG,CA8DA,SAASuK,GAAUvK,EAAQwK,GACvB,OAAOtR,EAAOsR,GAAU,SAAUC,EAAQC,GACtC,IAAIjS,EAASiS,EAAS1K,GAItB,OAFAvH,EAAOxB,QAAUwT,EAAOlP,KAAK9C,GAEtBgS,CACX,GAAG,GACP,CAiCA,IAAIE,GAAetS,EAAQkS,IAAU,GAkBjCnK,GAASiI,GAAYlB,IASzB,SAASyD,GAAS5K,EAAQ6K,GAGtB,IAFA,IAAIpS,EAAS,GAEJvB,EAAI,EAAGA,EAAI2T,EAAO3T,IACvBuB,GAAUuH,EAGd,OAAOvH,CACX,CAUA,SAASqS,GAAa9K,EAAQ+K,EAAM5T,GAKhC,OAJKiB,EAAM4H,IAA4B,WAAjB7F,EAAK6F,KACvBA,EAASP,OAAOO,IAGb4K,GAAQnL,OAAOsL,GAAM,IAAM,GAAI1R,KAAK2R,KAAK7T,EAAM6I,EAAO/I,QACjE,CA+FA,IAAIgU,GAAU7T,EAAcW,EAAQ0H,OAAOxF,UAAUgR,UAkBjDlE,GAAQhR,EAAOgC,EAAQ0H,OAAOxF,UAAU8M,QAmBxCmE,GAAU7S,EAAQ0O,IAAO,GAUzBoE,GAAUpT,EAAQ0H,OAAOxF,UAAUmR,QA8EvCjW,EAAQQ,GAAKA,EACbR,EAAQkW,QA93FR,SAAkBrI,GACd,IAAKvM,MAAMC,QAAQsM,GACf,MAAMvH,EAAkBuH,EAAW,SAGvC,OAAO,WAIH,IAHA,IACIvK,EADAtB,EAAM6L,EAAU/L,OAGXC,EAAI,EAAGA,EAAIC,GAGXgB,EAFLM,EAASuK,EAAU9L,GAAGP,MAAMjB,KAAMkB,YADbM,KAQzB,OAAOuB,CACX,CACJ,EA42FAtD,EAAQmG,IAAMA,GACdnG,EAAQyP,MAAQA,GAChBzP,EAAQmW,OA/8NR,SAAiB9T,GACb,OAAO,WACH,OAAOA,CACX,CACJ,EA48NArC,EAAQ0P,MAAQA,GAChB1P,EAAQmF,OAASA,EACjBnF,EAAQiF,SAAWA,EACnBjF,EAAQkO,YAAcA,GACtBlO,EAAQwB,MAAQA,GAChBxB,EAAQmO,QAAUA,GAClBnO,EAAQS,OAASA,EACjBT,EAAQ2P,QAAUA,GAClB3P,EAAQ4L,QAAUA,GAClB5L,EAAQoW,UA57GR,SAAoBvV,GAChB,OAAOuN,GAAWvN,EAAI,GAC1B,EA27GAb,EAAQY,OAASA,EACjBZ,EAAQqW,MAhvFR,SAAgB3P,EAAW7F,GACvB,OAAO,WACH,OAAO6F,EAAUlF,MAAMjB,KAAMkB,WAAaZ,EAAGW,MAAMjB,KAAMkB,gBAAa,CAC1E,CACJ,EA6uFAzB,EAAQsW,QA9wDR,SAAkB5P,EAAW6P,EAASC,EAAUC,GAC5C,OAAO,SAAUC,GACb,IAAIC,EAAYvV,EAAQyQ,GAAW,CAAC6E,EAAKlW,EAAIiW,IAE7C,OAAO/P,EAAUlF,MAAMkV,EAAKrT,EAAImT,EAAUG,IAAc,GAAK,CAACJ,EAASC,EAC3E,CACJ,EAywDAxW,EAAQe,MAAQA,EAChBf,EAAQmC,YAAcA,EACtBnC,EAAQ4W,QAn6GR,SAAkB/I,GACd,IAAKvM,MAAMC,QAAQsM,GACf,MAAMvH,EAAkBuH,EAAW,SAGvC,OAAO,WACH,OAAOxK,EAAIwK,EAAWM,GAAQ1M,WAClC,CACJ,EA45GAzB,EAAQsC,QAAUA,EAClBtC,EAAQ6W,UAttFR,SAAoBnQ,EAAWoQ,EAAQC,GACnC,OAAO,WACH,OAAQrQ,EAAUlF,MAAMjB,KAAMkB,WAAaqV,EAASC,GAASvV,MAAMjB,KAAMkB,UAC7E,CACJ,EAmtFAzB,EAAQqF,SAAWA,EACnBrF,EAAQ0F,MAAQA,EAChB1F,EAAQ2F,QAAUA,EAClB3F,EAAQgX,MAvzGR,SAAgBnW,EAAIgL,GAChB,OAAO8C,GAAO9N,EAAIgL,GAAO,EAC7B,EAszGA7L,EAAQiX,WA1uGR,SAAqBpW,EAAIgL,GACrB,OAAO8C,GAAO9N,EAAIgL,GAAO,EAC7B,EAyuGA7L,EAAQkX,UA5xGR,SAAoBrW,EAAIgL,GACpB,OAAO8C,GAAO9N,EAAIgL,GAAO,GAAO,EACpC,EA2xGA7L,EAAQmX,eApwGR,SAAyBtW,EAAIgL,GACzB,OAAO8C,GAAO9N,EAAIgL,GAAO,GAAM,EACnC,EAmwGA7L,EAAQoX,SAjtGR,SAAmBvW,EAAIwW,GACnB,IAAIC,EAEJ,OAAO,WACH,IAAIjW,EAAOI,UACP8V,EAAY,WACZD,EAAY,KACZzW,EAAGW,MAAMjB,KAAMc,EACnB,EAAEyB,KAAKvC,MAEPiX,aAAaF,GACbA,EAAYG,WAAWF,EAAWF,EACtC,CACJ,EAqsGArX,EAAQwQ,OAASA,GACjBxQ,EAAQ8G,WAAaA,EACrB9G,EAAQyQ,OAASA,GACjBzQ,EAAQ0Q,SAAWA,GACnB1Q,EAAQkH,KAAOA,EACflH,EAAQiH,SAAWA,EACnBjH,EAAQ2H,cAAgBA,EACxB3H,EAAQ4H,UAAYA,EACpB5H,EAAQgS,YAAcA,GACtBhS,EAAQgI,MAAQA,EAChBhI,EAAQ+H,QAAUA,EAClB/H,EAAQyG,OAASA,EACjBzG,EAAQiI,WAAaA,EACrBjI,EAAQoI,KAAOA,GACfpI,EAAQmI,UAAYA,EACpBnI,EAAQqI,eAAiBA,GACzBrI,EAAQuI,SAAWA,GACnBvI,EAAQsI,cAAgBA,GACxBtI,EAAQwI,mBAAqBA,GAC7BxI,EAAQyI,cAAgBA,GACxBzI,EAAQ0I,UAAYA,GACpB1I,EAAQ2I,QAAUA,GAClB3I,EAAQgJ,YAAcA,GACtBhJ,EAAQuJ,QAAUA,GAClBvJ,EAAQ0X,KA/sGR,SAAe7W,GACX,OAAO,WACH,IAAIQ,EAAOoJ,GAAKjJ,MAAM,KAAMC,WAAWiN,UAEvC,OAAO7N,EAAGW,MAAMjB,KAAMc,EAC1B,CACJ,EA0sGArB,EAAQyC,QAAUA,EAClBzC,EAAQ2X,UAzvDR,SAAoBC,GAChB,IAAItU,EAAS,CAAC,EAMd,OAJAb,EAAQmV,GAAW,SAAUC,GACzBvU,EAAOuU,EAAK,IAAMA,EAAK,EAC3B,IAEOvU,CACX,EAkvDAtD,EAAQ8X,SAzyER,SAAmBxT,EAAOtC,EAAKW,GAG3B,IAFA,IAAIW,EAAS,CAACgB,GAELvC,EAAI,EAAGgW,EAAQ/V,EAAM,EAAGD,EAAIgW,EAAOhW,IACxCuB,EAAO8C,KAAKzD,EAASW,EAAOvB,GAAIA,EAAGuB,IAGvC,OAAOA,CACX,EAkyEAtD,EAAQ4C,QAAUA,EAClB5C,EAAQgY,SAtrGR,SAAmBnU,GACf,OAAO,WACH,OAAOpC,UAAU+H,GAAgB3F,EAAKpC,UAAUK,QACpD,CACJ,EAmrGA9B,EAAQ2J,MAAQA,GAChB3J,EAAQ4K,MAAQA,GAChB5K,EAAQyJ,SAAWA,GACnBzJ,EAAQ8K,OAASA,GACjB9K,EAAQiS,QAAUA,GAClBjS,EAAQ6R,UAAYA,GACpB7R,EAAQ4J,MAAQA,GAChB5J,EAAQ6J,QAAUA,GAClB7J,EAAQ4P,GAAKA,GACb5P,EAAQ6P,IAAMA,GACd7P,EAAQqG,IAAMA,GACdrG,EAAQkS,OAASA,GACjBlS,EAAQiY,YAtmDR,SAAsBxS,EAAKpD,GACvB,OAAO,SAAUwI,GACb,OAAO7H,EAAYX,GACbgE,GAAIwE,EAAQpF,IAAQoF,EAAOpF,KAASpD,EACpC5B,EAAO4B,EAAOwI,EAAOpF,GAC/B,CACJ,EAimDAzF,EAAQmS,OAASA,GACjBnS,EAAQqS,UAAYA,GACpBrS,EAAQkY,aA7jDR,SAAuBvG,EAAMtP,EAAOgI,GAChC,OAAO,SAAUQ,GACb,IAAIsK,EAAW7D,GAAazG,EAAQ6G,GAAaC,EAAMtH,IAAY,GAEnE,OAAO8K,EAAS1D,SAAWhR,EAAO0U,EAASrP,OAAQzD,EACvD,CACJ,EAwjDArC,EAAQ8J,KAAOA,GACf9J,EAAQoC,SAAWA,EACnBpC,EAAQ0J,MAAQA,GAChB1J,EAAQ+J,QAAUA,GAClB/J,EAAQgK,KAAOA,GACfhK,EAAQiK,OAASA,GACjBjK,EAAQmK,SAAWA,GACnBnK,EAAQmY,aAx+JR,SAAuBzX,EAAGC,GACtB,IAAI2C,EAAS,GACT8U,EAAe,IAAIvS,EACnBwS,EAAU,IAAIxS,EAAclF,GAC5B2X,EAAO5X,EAAEoB,OAEb,GAAIwW,GAAQ3X,EAAEmB,OACV,IAAK,IAAWkF,EAAPjF,EAAI,EAAMA,EAAIuW,EAAMvW,IACzBiF,EAAItG,EAAEqB,IAEDqW,EAAa/R,IAAIW,IAAMqR,EAAQhS,IAAIW,KACpCoR,EAAajS,IAAIa,GACjB1D,EAAO8C,KAAKY,IAKxB,OAAO1D,CACX,EAu9JAtD,EAAQuY,OAroGR,SAAiBxJ,EAAYC,GACzB,OAAO5N,EAAQ0N,GAAS,CAACC,EAAYC,GACzC,EAooGAhP,EAAQwY,SA9mGR,SAAmB1S,GACf,OAAO1E,EAAQ0N,GAAS,CAACtO,EAAI,GAAIsF,GACrC,EA6mGA9F,EAAQ8P,GAAKA,GACb9P,EAAQyY,SA1yER,SAAoBpW,GAChB,MAAuB,WAAhB2C,EAAK3C,IAAuBoW,SAASpW,EAChD,EAyyEArC,EAAQ+P,KAAOA,GACf/P,EAAQgQ,MAAQA,GAChBhQ,EAAQoF,KAAOA,EACfpF,EAAQ0Y,aAvHR,SAAuBC,GACnB,OAAO,SAAUjC,GACb,OAAOA,aAAeiC,CAC1B,CACJ,EAoHA3Y,EAAQ2Q,UAAYA,GACpB3Q,EAAQkQ,KAAOA,GACflQ,EAAQoQ,MAAQA,GAChBpQ,EAAQiD,MAAQA,EAChBjD,EAAQ+C,OAASA,EACjB/C,EAAQoD,MAAQA,EAChBpD,EAAQ4Y,cA/vER,SAAwBvW,GACpB,OAAOsO,GAAUtO,IAAU6B,KAAKE,IAAI/B,IApkJjB,gBAqkJvB,EA8vEArC,EAAQ6Y,OA1GR,SAAiBC,GACb,OAAO,SAAUzW,GACb,OAAO2C,EAAK3C,KAAWyW,CAC3B,CACJ,EAuGA9Y,EAAQgD,YAAcA,EACtBhD,EAAQoK,KAAOA,GACfpK,EAAQuK,SAAWA,GACnBvK,EAAQ+Y,aAxhDR,SAAuBrS,EAAWjB,GAC9B,OAAO,SAAUoF,GACb,OAAOnE,EAAU5F,KAAKP,KAAMsK,EAAOpF,GACvC,CACJ,EAqhDAzF,EAAQsS,KAAOA,GACftS,EAAQwK,KAAOA,GACfxK,EAAQyK,KAAOA,GACfzK,EAAQiQ,GAAKA,GACbjQ,EAAQmQ,IAAMA,GACdnQ,EAAQuS,KAAOA,GACfvS,EAAQqD,IAAMA,EACdrD,EAAQgZ,QA9mGR,SAAkBnY,EAAIoY,GAClB,OAAOrL,GAAK,CAACnD,GAAMlH,EAAQ0V,GAASzX,GAAMX,IAC9C,EA6mGAb,EAAQ0S,UAAYA,GACpB1S,EAAQ2S,cAAgBA,GACxB3S,EAAQuD,QAAUA,EAClBvD,EAAQkZ,KA/vER,SAAeC,GACX,OAAOpV,EAAOoV,GAAS,SAAUC,EAAGpY,GAChC,OAAQA,EAAIoY,CAChB,GAAG,GAAKD,EAAQrX,MACpB,EA4vEA9B,EAAQqZ,OA7uER,SAAiBF,GACb,IAMI7V,EANAtB,EAAMmX,EAAQrX,SAAW,EAE7B,GAAY,IAARE,EACA,OAAOb,IAIX,IAAImY,EAAgBjW,EAAI8V,EAASI,QAAQzM,KAAKyD,IAE9C,GAAIvO,EAAM,GAAM,EAAG,CACf,IAAIgL,EAAQhL,EAAM,EAElBsB,GAAUgW,EAActM,EAAQ,GAAKsM,EAActM,IAAU,CACjE,MACI1J,EAASgW,GAAetX,EAAM,GAAK,GAGvC,OAAOsB,CACX,EA2tEAtD,EAAQ6S,MAAQA,GAChB7S,EAAQ8S,SAAWA,GACnB9S,EAAQwZ,OArsER,SAAiB9Y,EAAGC,GAChB,OAAOD,EAAKC,EAAIuD,KAAKC,MAAMzD,EAAIC,EACnC,EAosEAX,EAAQ4Q,SAAWA,GACnB5Q,EAAQ6Q,WAAaA,GACrB7Q,EAAQqQ,IAAMA,GACdrQ,EAAQiT,SAAWA,GACnBjT,EAAQmT,UAAYA,GACpBnT,EAAQyZ,QApUR,SAAkB5O,EAAQ+K,EAAM5T,GAC5B,OAAO2T,GAAY9K,EAAQ+K,EAAM5T,GAAO6I,CAC5C,EAmUA7K,EAAQ0Z,SA7SR,SAAmB7O,EAAQ+K,EAAM5T,GAC7B,OAAO6I,EAAS8K,GAAY9K,EAAQ+K,EAAM5T,EAC9C,EA4SAhC,EAAQoT,MAAQA,GAChBpT,EAAQoB,QAAUA,EAClBpB,EAAQ2Z,aAnmNR,SAAuB9Y,EAAIQ,GACvB,OAAO,WACH,IAAKC,MAAMC,QAAQF,GACf,OAAOR,EAAGW,MAAMjB,KAAMkB,WAQ1B,IALA,IAK0BC,EALtBC,EAAUF,UAAUK,OAAS,EAC7BD,EAAUR,EAAKS,OACfkN,EAAY1N,MAAMO,GAClBD,EAAU,GAELG,EAAIF,EAAU,EAAaE,GAAK,EAAGA,IACxCL,EAAWL,EAAKU,GAChBiN,EAAUjN,GAAKL,IAAalB,EAAKiB,UAAUE,KAAaD,EAG5D,IAAKK,EAAI,EAAGA,GAAKJ,EAASI,IACtBH,EAAQG,GAAKN,UAAUM,GAG3B,IAAK,IAAIqH,EAAI,EAAGA,EAAIvH,EAASuH,IACzBxH,EAAQG,KAAOiN,EAAU5F,GAG7B,OAAOvI,EAAGW,MAAMjB,KAAMqB,EAC1B,CACJ,EA0kNA5B,EAAQ0K,UAAYA,GACpB1K,EAAQ2K,cAAgBA,GACxB3K,EAAQsT,WAAaA,GACrBtT,EAAQqT,aAAeA,GACvBrT,EAAQ4Z,cAvsCR,SAAwBlT,EAAWiL,EAAMtH,GACrC,OAAO,SAAUQ,GACb,IAAIsK,EAAW7D,GAAazG,EAAQ6G,GAAaC,EAAMtH,IAAY,GAEnE,OAAO3D,EAAU5F,KAAKP,KAAM4U,EAASrP,OACzC,CACJ,EAksCA9F,EAAQyT,KAAOA,GACfzT,EAAQ0T,OAASA,GACjB1T,EAAQuT,OAASA,GACjBvT,EAAQ4N,KAAOA,GACf5N,EAAQ+K,MAAQA,GAChB/K,EAAQ6Z,UA7vJR,SAAoBnX,EAAW+C,GAC3B,OAAOpC,EAAIX,EAAWoI,GAAOrF,GACjC,EA4vJAzF,EAAQkL,KAAOA,GACflL,EAAQgL,SAAWA,GACnBhL,EAAQ8Z,UAvqER,SAAoB7Y,EAAKC,GACrB,OAAOgD,KAAKC,MAAMD,KAAK6V,UAAY7Y,EAAMD,EAAM,GAAKA,EACxD,EAsqEAjB,EAAQga,MA9nER,SAAgB1V,EAAOyT,EAAOtU,GAK1B,GAJAa,EAAQwM,GAAexM,GACvByT,EAAQjH,GAAeiH,GAGV,KAFbtU,EAA4B,IAArBhC,UAAUK,OAAegP,GAAerN,GAAQ,GAGnD,OAAOsU,IAAUzT,EAAQ,GAAK,CAACA,GAMnC,IAHA,IAAItC,EAAMkC,KAAKhD,IAAIgD,KAAK2R,MAAMkC,EAAQzT,GAASb,GAAO,GAClDH,EAAShC,MAAMU,GAEVD,EAAI,EAAGyI,EAAOlG,EAAOvC,EAAIC,EAAKD,IACnCuB,EAAOvB,GAAKyI,EACZA,GAAQ/G,EAGZ,OAAOH,CACX,EA6mEAtD,EAAQ+D,OAASA,EACjB/D,EAAQmL,YAAcA,GACtBnL,EAAQoL,gBAAkBA,GAC1BpL,EAAQgE,WAAaA,EACrBhE,EAAQia,UA3lER,SAAoBvZ,EAAGC,GACnB,OAAOD,EAAIC,CACf,EA0lEAX,EAAQ+T,OAASA,GACjB/T,EAAQ2T,SAAWA,GACnB3T,EAAQka,WApgCR,SAAqBrZ,GACjB,OAAO,SAAUgK,GACb,OAAO8I,GAAS9I,EAAQhK,EAAGgK,GAC/B,CACJ,EAigCA7K,EAAQma,OAlTR,SAAiBtP,EAAQ6K,GACrB,GAAIzS,EAAM4H,GACN,MAAMvE,EAAkBuE,EAAQ,UAGpC,OAAO4K,GAAQ5K,EAAQ3G,KAAKC,MAAMuR,GACtC,EA6SA1V,EAAQ8V,QAAUA,GAClB9V,EAAQ0O,QAxpJR,SAAkBhM,GAId,IAHA,IAAIV,EAAMQ,EAAeE,EAAUZ,QAC/BwB,EAAShC,MAAMU,GAEVD,EAAI,EAAGsN,EAAMrN,EAAM,EAAGD,EAAIC,EAAKD,IACpCuB,EAAOvB,GAAKW,EAAU2M,EAAMtN,GAGhC,OAAOuB,CACX,EAgpJAtD,EAAQqL,OAASA,GACjBrL,EAAQwL,SAAWA,GACnBxL,EAAQ2L,MAAQA,GAChB3L,EAAQiU,MAAQA,GAChBjU,EAAQ8L,SAAWA,GACnB9L,EAAQkU,OAASA,GACjBlU,EAAQoa,QAnzBR,SAAkBzI,EAAMtP,EAAOgI,GAC3B,OAAO,SAAUQ,GACb,OAAO0J,GAAU1J,EAAQ8G,EAAMtP,EAAOgI,EAC1C,CACJ,EAgzBArK,EAAQuU,UAAYA,GACpBvU,EAAQ+L,eAAiBA,GACzB/L,EAAQ2U,KAAOA,GACf3U,EAAQ4U,OAASA,GACjB5U,EAAQwU,OAASA,GACjBxU,EAAQqE,MAAQA,EAChBrE,EAAQ2E,QAAUA,EAClB3E,EAAQiM,KAAOA,GACfjM,EAAQgM,OAASA,GACjBhM,EAAQ8M,KAAOA,GACf9M,EAAQmN,SAAWA,GACnBnN,EAAQqa,aAnrIR,SAAuB3X,EAAW8C,EAASqH,GACvC,IAAIvJ,EAASe,EAAM3B,EAAW,EAAGA,EAAUZ,QAE3C,GAAyB,IAArBL,UAAUK,OACV,OAAOwB,EAGX,IACIO,EAAMkJ,GAAmBzJ,EAAQkC,EAAS0G,GAD/BU,GAAcC,IACyC,EAAGvJ,EAAOxB,QAIhF,OAFAwB,EAAO4G,OAAOrG,EAAK,EAAG2B,GAEflC,CACX,EAuqIAtD,EAAQiN,OAASA,GACjBjN,EAAQkN,WAAaA,GACrBlN,EAAQ4R,MAAQA,GAChB5R,EAAQ+V,QAAUA,GAClB/V,EAAQuQ,SAAWA,GACnBvQ,EAAQsQ,IAAMA,GACdtQ,EAAQsa,oBAhlIR,SAA8B5Z,EAAGC,GAC7B,OAAOmG,EAAWpG,EAAGC,GAAGuE,OAAO4B,EAAWnG,EAAGD,GACjD,EA+kIAV,EAAQoN,KAAOA,GACfpN,EAAQsN,KAAOA,GACftN,EAAQqN,SAAWA,GACnBrN,EAAQuN,cAAgBA,GACxBvN,EAAQwN,UAAYA,GACpBxN,EAAQua,QAnqGR,SAAkB1Z,EAAI2Z,GAClB,OAAO,WAKH,IAJA,IAAIxY,EAAMP,UAAUK,OAChB2Y,EAAaD,EAAQ1Y,OACrBT,EAAO,GAEFU,EAAI,EAAGA,EAAIC,EAAKD,IACrBV,EAAK+E,KAAKrE,EAAI0Y,EAAaD,EAAQzY,GAAGN,UAAUM,IAAMN,UAAUM,IAGpE,OAAOlB,EAAGW,MAAMjB,KAAMc,EAC1B,CACJ,EAwpGArB,EAAQ8U,KAAOA,GACf9U,EAAQ+U,QAAUA,GAClB/U,EAAQ0a,SA7PR,SAAmBC,GACf,OAAO,SAAUC,GACb,OAAgC,IAAzB5E,GAAQ4E,EAAGD,EACtB,CACJ,EA0PA3a,EAAQ6a,SAroGR,SAAmBha,EAAIwW,GACnB,IAAI/T,EACAwX,EAAW,EAEf,OAAO,WACH,IAAIC,EAAMC,KAAKD,MAOf,OALIA,EAAMD,GAAYzD,IAClByD,EAAWC,EACXzX,EAASzC,EAAGW,MAAMjB,KAAMkB,YAGrB6B,CACX,CACJ,EAwnGAtD,EAAQyN,UAAYA,GACpBzN,EAAQgF,KAAOA,EACfhF,EAAQib,MAvmGR,SAAgBpa,GACZ,OAAO,SAAUH,GACb,OAAOG,EAAGC,KAAKP,KAAMG,EACzB,CACJ,EAomGAV,EAAQ+N,MAAQA,GAChB/N,EAAQ8N,QAAUA,GAClB9N,EAAQ6G,QAAUA,EAClB7G,EAAQ2G,UAAYA,EACpB3G,EAAQkb,OAxlFR,SAAiBxU,EAAW7F,GACxB,OAAO,SAAUwB,GACb,OAAOqE,EAAU5F,KAAKP,KAAM8B,GAASA,EAAQxB,EAAGC,KAAKP,KAAM8B,EAC/D,CACJ,EAqlFArC,EAAQmb,SAx0HR,SAAmBzR,EAAOgC,GACtB,OAAO,SAAUhJ,GACb,OAAO+I,GAAU/I,EAAWgH,EAAO,KAAMgC,EAC7C,CACJ,EAq0HA1L,EAAQgV,SAAWA,GACnBhV,EAAQgO,YAAcA,GACtBhO,EAAQiV,UAAYA,GACpBjV,EAAQob,WAziBR,SAAqBzJ,EAAMjG,EAASrB,GAChC,OAAO,SAAUQ,GACb,OAAOqK,GAAarK,EAAQ8G,EAAMjG,EAASrB,EAC/C,CACJ,EAsiBArK,EAAQkV,aAAeA,GACvBlV,EAAQoV,SAAWA,GACnBpV,EAAQwV,aAAeA,GACvBxV,EAAQiL,OAASA,GACjBjL,EAAQqb,KAnkFR,SAAe3U,EAAW7F,GACtB,OAAO,SAAUwB,GACb,OAAOqE,EAAU5F,KAAKP,KAAM8B,GAASxB,EAAGC,KAAKP,KAAM8B,GAASA,CAChE,CACJ,EAgkFArC,EAAQsb,IA7xHR,SAAc5a,EAAGC,GACb,OAAO8M,GAAU,CAAC/M,EAAGC,GACzB,EA4xHAX,EAAQiO,aAAeA,EAE1B","sourcesContent":["/**\n* @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming.\n* @author Andrea Scartabelli \n* @version 0.61.1-beta.1\n* @module lamb\n* @license MIT\n*/\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.lamb = {}));\n})(this, (function (exports) { 'use strict';\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 */\n var __ = {};\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 */\n function 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.
\n * With this comparison NaN is equal to itself, but 0 and -0 are\n * considered the same value.
\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 */\n function 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.
\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 */\n function 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.
\n * The function will convert to number all its parameters before starting any\n * evaluation, and will return NaN if min is greater\n * than max.\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 */\n function 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.
\n * The {@link module:lamb.__|__} object can be used as a placeholder for arguments.
\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 */\n function 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.
\n * The shouldAritize parameter is for the \"reduce\" functions, where\n * the absence of the initialValue transforms a \"fold\" operation into a\n * \"reduce\" one.\n * @private\n * @param {Function} fn\n * @param {Boolean} shouldAritize\n * @returns {Function}\n */\n function _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 min\n * and a max 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 */\n var 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 */\n function 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 */\n function compose (a, b) {\n return arguments.length ? function () {\n return a.call(this, b.apply(this, arguments));\n } : identity;\n }\n\n var MAX_ARRAY_LENGTH = 4294967295;\n var MAX_SAFE_INTEGER = 9007199254740991;\n\n /**\n * Converts a value to a valid array length, thus an integer within\n * 0 and 232 - 1 (both included).\n * @private\n * @param {*} value\n * @returns {Number}\n */\n function _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 iteratee for each element of the given array-like object.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example Adding a CSS class to all elements of a NodeList in a browser environment:\n * 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 */\n function 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 */\n var generic = Function.bind.bind(Function.call);\n\n /**\n * Verifies if a value is null.\n * @example\n * _.isNull(null) // => true\n * _.isNull(void 0) // => false\n * _.isNull(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for undefined too.\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\n function isNull (value) {\n return value === null;\n }\n\n /**\n * Verifies if a value is undefined.\n * @example\n * _.isUndefined(null) // => false\n * _.isUndefined(void 0) // => true\n * _.isUndefined(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for null too.\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\n function isUndefined (value) {\n return value === void 0;\n }\n\n /**\n * Verifies if a value is null or undefined.\n * @example\n * _.isNil(NaN) // => false\n * _.isNil({}) // => false\n * _.isNil(null) // => true\n * _.isNil(void 0) // => true\n * _.isNil() // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNull|isNull}\n * @see {@link module:lamb.isUndefined|isUndefined}\n * @since 0.1.0\n * @param {*} value\n * @returns {Boolean}\n */\n function 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 */\n function _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}.
\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.
\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 */\n var 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.
\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 */\n function 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 */\n var 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.
\n * The difference is that the bound arguments will be appended to the ones received by\n * the resulting function.\n * @example\n * Explaining the difference with partial:\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 * Explaining placeholder substitutions:\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 */\n function 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 step parameter must be 1\n * to build {@link module:lamb.reduce|reduce} and -1 to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\n function _makeReducer (step) {\n return function (arrayLike, accumulator, initialValue) {\n var len = _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 accumulator function.
\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 */\n var reduce = _makeReducer(1);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduce} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * 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 */\n var reduceWith = _makePartial3(reduce, true);\n\n /**\n * Converts a value to an integer.\n * @private\n * @param {*} value\n * @returns {Number}\n */\n function _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.
\n * Note that unlike the native array method this function ensures that dense\n * arrays are returned.
\n * Also, unlike the native method, the start and end\n * parameters aren't optional and will be simply converted to integer.
\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 */\n function 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 start and end bounds, builds a partial application\n * of {@link module:lamb.slice|slice} expecting the array-like object to slice.
\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 */\n var sliceAt = _makePartial3(slice);\n\n var 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 */\n function 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 */\n function 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 */\n var append = _curry2(appendTo, true);\n\n /**\n * Checks if an array-like object contains the given value.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * 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 */\n function 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.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * 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 */\n var 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 */\n function _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 * iteratee, 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 */\n var 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 */\n var countBy = _curry2(count, true);\n\n var 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 */\n function _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 */\n function _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 */\n function _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 predicate\n * test.
\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 */\n function 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.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n function 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.
\n * Note that this function uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n var 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 */\n function 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 n elements of the given array or array-like object.\n * Note that, being this only a shortcut for a specific use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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 */\n function 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.
\n * See the note and examples for {@link module:lamb.dropFrom|dropFrom} about passing a\n * negative n.\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 */\n var 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 */\n function _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 */\n function _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 */\n var 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 */\n var 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 */\n function _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.
\n * The function will stop calling the predicate as soon as it returns a falsy value.
\n * Note that an empty array-like will always produce a true result regardless of the\n * predicate because of [vacuous truth]{@link https://en.wikipedia.org/wiki/Vacuous_truth}.
\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 Showing the difference with Array.prototype.every:\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 */\n var 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 */\n var 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 */\n var 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 */\n function _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 -1 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 */\n function 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 undefined 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 */\n function 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 */\n var 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 -1 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 */\n function 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 undefined 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 */\n function 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 */\n var 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 */\n var 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 */\n var 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 Showing the difference with map:\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 */\n function 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 */\n var 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 */\n function _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 */\n var _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 Showing the difference with shallowFlatten:\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 */\n var 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.
\n * Returns NaN otherwise.\n * @private\n * @param {Number} idx\n * @param {Number} len\n * @returns {Number}\n */\n function _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.
\n * Like {@link module:lamb.slice|slice} the index can be negative.
\n * If the index isn't supplied, or if its value isn't an integer within the array-like bounds,\n * the function will return undefined.
\n * getIndex will throw an exception when receives null or\n * undefined in place of an array-like object, but returns undefined\n * for any other value.\n * @example\n * 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 */\n function 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 Using negative indexes:\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 */\n var 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 Adding a custom value for missing keys:\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 */\n var 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 */\n var groupBy = _curry2(group, true);\n\n /**\n * Retrieves the first element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.head([1, 2, 3]) // => 1\n * _.head(\"hello\") // => \"h\"\n * _.head([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.last|last}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var 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.
\n * Should be used only when you're sure that your iteratee won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * 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 Result of an iteratee producing a duplicate key:\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 */\n var 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 */\n var 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 */\n var init = partial(slice, [__, 0, -1]);\n\n /**\n * Inserts the provided element in a copy of an array-like object at the\n * specified index.
\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.
\n * Negative indexes are allowed; when a negative index is out of bounds\n * the element will be inserted at the start of the resulting array.\n * @example\n * 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 */\n function 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 */\n var 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.
\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 */\n function 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.
\n * Note that unlike the native method, this function won't convert\n * null and undefined values in the array to empty\n * strings and that the separator parameter isn't optional.
\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 Showing the differences with the native array method:\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 */\n function 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.
\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 */\n var joinWith = _curry2(join, true);\n\n /**\n * Retrieves the last element of an array-like object.
\n * Just a common use case of {@link module:lamb.getAt|getAt} exposed for convenience.\n * @example\n * _.last([1, 2, 3]) // => 3\n * _.last(\"hello\") // => \"o\"\n * _.last([]) // => undefined\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.head|head}\n * @see {@link module:lamb.getIndex|getIndex}, {@link module:lamb.getAt|getAt}\n * @since 0.16.0\n * @param {ArrayLike} arrayLike\n * @returns {*}\n */\n var 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.
\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 */\n function _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.
\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 */\n var 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}\n */\n function 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 */\n var 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 */\n function getIn (source, key) {\n return source[key];\n }\n\n /**\n * A curried version of {@link module:lamb.getIn|getIn}.
\n * Receives a property name and builds a function expecting the object from which we want to retrieve\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 */\n var 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 */\n var 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 */\n function 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.
\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 It's not the same as {@link module:lamb.difference|difference}:\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 */\n function 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.
\n * The new function will create an array copy of the array-like without\n * the specified values.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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 */\n var 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.
\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 */\n var reduceRight = _makeReducer(-1);\n\n /**\n * A partial application of {@link module:lamb.reduce|reduceRight} that uses the\n * provided accumulator and the optional initialValue to\n * build a function expecting the array-like object to act upon.\n * @example\n * 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 */\n var 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 */\n function 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 */\n function 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}.
\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 */\n var rotateBy = _curry2(rotate, true);\n\n /**\n * Sets an index in an array-like object.
\n * If provided with an updater function it will use it to update the current value,\n * otherwise sets the index to the specified value.\n * @private\n * @param {ArrayLike} arrayLike\n * @param {Number} idx\n * @param {*} [value]\n * @param {Function} [updater]\n * @returns {Array}\n */\n function _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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 Using negative indexes:\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 */\n var setAt = _makePartial3(_setIndex);\n\n /**\n * Builds a new function that passes only the specified amount of arguments to the original one.
\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 Using a negative arity:\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 */\n function 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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 */\n var setIndex = aritize(_setIndex, 3);\n\n /**\n * Flattens the \"first level\" of an array.\n * @example Showing the difference with flatten:\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 */\n var shallowFlatten = _makeArrayFlattener(false);\n\n /**\n * Checks if at least one element in an array-like object satisfies the given predicate.
\n * The function will stop calling the predicate as soon as it returns a truthy value.
\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 Showing the difference with Array.prototype.some:\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 */\n var 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 */\n var 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 */\n function _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.
\n * If the given values are of different types they\n * will be both converted to strings.
\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\n function _comparer (a, b) {\n var result = 0;\n\n if (typeof a !== typeof b) {\n a = String(a);\n b = String(b);\n }\n\n if (!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 */\n function _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 */\n function _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 */\n function _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.
\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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used\n * in the comparison.
\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 Stable sort:\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 Stable multi-sort:\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 Using custom comparers:\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 */\n function 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 */\n function _getInsertionIndex (array, element, comparer, start, end) {\n if (array.length === 0) {\n return 0;\n }\n\n var pivot = (start + end) >> 1;\n var result = comparer(\n { value: element, 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 With simple values:\n * _.sortedInsert([], 1) // => [1]\n * _.sortedInsert([2, 4, 6], 5) // => [2, 4, 5, 6]\n * _.sortedInsert([4, 2, 1], 3, _.sorterDesc()) // => [4, 3, 2, 1]\n *\n * @example With complex values:\n * 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 */\n function 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 reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorterDesc|sorterDesc}\n * @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 */\n var sorter = partial(_sorter, [__, false, __]);\n\n /**\n * Creates a descending sort criterion with the provided reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}\n * @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 */\n var 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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in\n * the comparison.
\n * See {@link module:lamb.sort|sort} for more examples.\n *\n * @example\n * var sortAsNumbers = _.sortWith([parseFloat]);\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * sortAsNumbers(weights) // => [\"1 Kg\", \"2 Kg\", \"7 Kg\", \"10 Kg\"]\n *\n * @memberof module:lamb\n * @category Array\n * @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 */\n var 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}.
\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 */\n function 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 */\n var tail = drop(1);\n\n /**\n * Retrieves the first n elements from an array or array-like object.
\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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 */\n function 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.
\n * See the note and examples for {@link module:lamb.takeFrom|takeFrom} about passing a\n * negative n.\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 */\n var 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 */\n var 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 */\n var takeWhile = _takeOrDropWhile(true, false);\n\n /**\n * Transposes a matrix. Can also be used to reverse a {@link module:lamb.zip|zip} operation.
\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example Transposing a matrix:\n * _.transpose([\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ]) // =>\n * // [\n * // [1, 4, 7],\n * // [2, 5, 8],\n * // [3, 6, 9]\n * // ]\n *\n * @example Showing the relationship with zip:\n * 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\n * @returns {Array}\n */\n function 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 */\n function 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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n function 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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 */\n var 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.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 */\n function updateAt (index, updater) {\n return function (arrayLike) {\n return _setIndex(arrayLike, index, null, updater);\n };\n }\n\n /**\n * Creates a copy of an array-like object with the given index changed by applying the\n * provided function to its value.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 */\n var 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.
\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}\n */\n function 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>}\n */\n var 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 */\n function 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 */\n var 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 */\n var 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.
\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 */\n function _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.
\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.
\n * The final application will happen when one of the generated functions is\n * invoked without placeholders, using the parameters collected so far.
\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 Explaining the function's behaviour:\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 Exploiting optional parameters:\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 */\n function 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 * collect.
\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 */\n function 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 */\n function _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 */\n function _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 _currier function.
\n * If the desumed arity isn't greater than one, it will return the received\n * function itself, instead.\n * @private\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @param {Boolean} [isRightCurry=false]\n * @param {Boolean} [isAutoCurry=false]\n * @returns {Function}\n */\n function _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.
\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 */\n function curry (fn, arity) {\n return _curry(fn, arity, false);\n }\n\n /**\n * Builds an auto-curried function. The resulting function can be called multiple times with\n * any number of arguments, and the original function will be applied only when the specified\n * (or derived) arity is consumed.
\n * Currying will start from the leftmost argument: use {@link module:lamb.curryableRight|curryableRight}\n * for right currying.\n * @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 */\n function curryable (fn, arity) {\n return _curry(fn, arity, false, true);\n }\n\n /**\n * Same as {@link module:lamb.curryable|curryable}, but currying starts from the rightmost argument.\n * @example\n * 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 */\n function curryableRight (fn, arity) {\n return _curry(fn, arity, true, true);\n }\n\n /**\n * Same as {@link module:lamb.curry|curry}, but currying starts from the rightmost argument.\n * @example\n * 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 */\n function curryRight (fn, arity) {\n return _curry(fn, arity, true);\n }\n\n /**\n * Returns a function that will execute the given function only if it stops being called for the\n * specified timespan.
\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call\n * happens immediately.\n * @example A common use case of debounce in a browser environment:\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 */\n function 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 */\n function 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.
\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.
\n * The resulting function will return undefined if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * 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 */\n function 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 undefined otherwise.
\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 args,\n * if present.\n * @private\n * @param {String} methodName\n * @param {Array} boundArgs\n * @param {Object} target\n * @param {...*} [args]\n * @returns {*}\n */\n function _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 * undefined.
\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.
\n * Returning undefined 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.
\n * See also {@link module:lamb.generic|generic} to create functions out of object methods.\n * @example Basic polymorphism with invoke:\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 With bound arguments:\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 */\n function 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 undefined.\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 */\n function 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 */\n function 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 */\n function 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.
\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 */\n function throttle (fn, timespan) {\n var result;\n var lastCall = 0;\n\n return function () {\n var now = Date.now();\n\n if (now - lastCall >= timespan) {\n lastCall = now;\n result = fn.apply(this, arguments);\n }\n\n return result;\n };\n }\n\n /**\n * Builds a function that passes only one argument to the given function.
\n * It's simply a shortcut for a common use case of {@link module:lamb.aritize|aritize},\n * exposed for convenience.\n * @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 */\n function 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-undefined value.
\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 */\n function 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.
\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 */\n function _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 * false 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 */\n var 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 true 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 */\n var anyOf = _checkPredicates(false);\n\n /**\n * Verifies that the two supplied values are the same value using the \"SameValue\" comparison.
\n * Note that this doesn't behave as the strict equality operator, but rather as a shim of ES6's\n * [Object.is]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is}.\n * Differences are that 0 and -0 aren't the same value and, finally,\n * NaN is equal to itself.
\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 */\n function 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}.
\n * The function will apply the received arguments to fn if the predicate is satisfied\n * with the same arguments, otherwise will return undefined.
\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 */\n function 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 trueFn,\n * if the predicate is satisfied with the same arguments, or to falseFn otherwise.
\n * Although you can use other conditions as trueFn or falseFn,\n * it's probably better to use {@link module:lamb.adapter|adapter} to build more complex behaviours.
\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 */\n function 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.
\n * Wraps the native > 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 */\n function 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 * >= operator, so -0 === 0.\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 */\n function gte (a, b) {\n return a >= b;\n }\n\n /**\n * A curried version of {@link module:lamb.areSame|areSame}.
\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.
\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 */\n var is = _curry2(areSame);\n\n /**\n * A right curried version of {@link module:lamb.gt|gt}.
\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 */\n var isGT = _curry2(gt, true);\n\n /**\n * A right curried version of {@link module:lamb.gte|gte}.
\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 */\n var isGTE = _curry2(gte, true);\n\n /**\n * Verifies that the first given value is less than the second.
\n * Wraps the native < 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 */\n function lt (a, b) {\n return a < b;\n }\n\n /**\n * A right curried version of {@link module:lamb.lt|lt}.
\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 */\n var 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 * <= operator, so -0 === 0.\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 */\n function lte (a, b) {\n return a <= b;\n }\n\n /**\n * A right curried version of {@link module:lamb.lte|lte}.
\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 */\n var 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 */\n function 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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.when|when} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its trueFn 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 */\n function 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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.unless|unless} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its falseFn 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 */\n function 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 */\n function 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 */\n var 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 */\n function 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 */\n var 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 */\n function 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 */\n var 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 */\n function 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.
\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 true 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 */\n function 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 true 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 */\n function 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 -(253 - 1) inclusive to\n * 253 - 1 inclusive.
\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 true 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 */\n function 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 */\n function 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 */\n function 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 */\n function modulo (a, b) {\n return a - (b * Math.floor(a / b));\n }\n\n /**\n * Multiplies two numbers.\n * @example\n * _.multiply(5, 3) // => 15\n *\n * @memberof module:lamb\n * @category Math\n * @see {@link module:lamb.multiplyBy|multiplyBy}\n * @since 0.1.0\n * @param {Number} a\n * @param {Number} b\n * @returns {Number}\n */\n function multiply (a, b) {\n return a * b;\n }\n\n /**\n * 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 */\n var 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 randomInt(0.1, 1.2) could be 2.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @since 0.1.0\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n function randomInt (min, max) {\n return Math.floor(Math.random() * (max - min + 1) + min);\n }\n\n /**\n * 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 */\n function _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 start up to,\n * but not including, limit, using the given step.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(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 Behaviour if step happens to be zero:\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 */\n function 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 */\n function 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 */\n var _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 */\n function _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 */\n function _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 */\n function _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 */\n function _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 */\n function _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.
\n * The path is a string with property names separated by dots by default, but\n * it can be customised with the optional third parameter.
\n * You can use integers in the path, even negative ones, to refer to array-like\n * object indexes, but the priority will be given to existing object keys:\n * the last example explains this particular case.\n * @example\n * 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 Accessing array-like objects indexes:\n * _.getPathIn(user, \"login.password.1\") // => \"b\"\n * _.getPathIn(user, \"scores.0\") // => {id: 1, value: 10}\n * _.getPathIn(user, \"scores.-1.value\") // => 30\n *\n * @example Priority will be given to existing object keys over indexes:\n * _.getPathIn(user, \"scores.-1\") // => {id: 3, value: 30}\n *\n * // let's do something funny\n * user.scores[\"-1\"] = \"foo bar\";\n *\n * _.getPathIn(user, \"scores.-1\") // => \"foo bar\";\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPath|getPath}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @since 0.19.0\n * @param {Object|ArrayLike} source\n * @param {String} path\n * @param {String} [separator=\".\"]\n * @returns {*}\n */\n function getPathIn (source, path, separator) {\n return _getPathInfo(source, _toPathParts(path, separator), true).target;\n }\n\n /**\n * Builds a checker function meant to be used with\n * {@link module:lamb.validate|validate}.
\n * Note that the function accepts multiple keyPaths as a means to\n * compare their values. In other words all the received keyPaths will be\n * passed as arguments to the predicate to run the test.
\n * If you want to run the same single property check with multiple properties, you should build\n * multiple checkers and combine them with {@link module:lamb.validate|validate}.\n * @example\n * 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 * [\"message\", [\"propertyA\", \"propertyB\"]] or an empty array.\n */\n function checker (predicate, message, keyPaths, pathSeparator) {\n return function (obj) {\n var getValues = partial(getPathIn, [obj, __, pathSeparator]);\n\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 */\n var _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 Showing the difference with {@link module:lamb.keys|keys}:\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 */\n var 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}.
\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>} pairsList\n * @returns {Object}\n */\n function fromPairs (pairsList) {\n var result = {};\n\n forEach(pairsList, function (pair) {\n result[pair[0]] = pair[1];\n });\n\n return result;\n }\n\n /**\n * Builds a partial application of {@link module:lamb.getPathIn|getPathIn} with the given\n * path and separator, expecting the object to act upon.
\n * @example\n * 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 */\n var 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 */\n function 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}.
\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 */\n var 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.
\n * @example Comparison with has:\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 */\n var hasOwn = generic(Object.prototype.hasOwnProperty);\n\n /**\n * Curried version of {@link module:lamb.hasOwn|hasOwn}.
\n * Returns a function expecting the object to check against the given key.\n * @example\n * 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 */\n var hasOwnKey = _curry2(hasOwn, true);\n\n /**\n * Builds a predicate expecting an object to check against the given key / value pair.
\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 */\n function 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.
\n * The value check is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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 */\n function 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 Object.keys.\n * @private\n * @function\n * @param {Object} source\n * @returns {String[]}\n */\n var _safeKeys = compose(Object.keys, Object);\n\n /**\n * Retrieves the list of the own enumerable properties of an object.
\n * Although [Object.keys]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys}\n * is already present in ECMAScript 5, its behaviour changed in the subsequent specifications\n * of the standard.
\n * This function shims the ECMAScript 6 version, by forcing a conversion to\n * object for any value but null and undefined.\n * @example Showing the difference with {@link module:lamb.enumerables|enumerables}:\n * 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 */\n var 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 */\n function 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.
\n * If the list of keys is longer than the values one, the keys will be created with\n * undefined values.
\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 */\n function 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 */\n function 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}.
\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 */\n var 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 */\n function _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.
\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.merge([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.merge(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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 */\n var 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 Showing the difference with merge:\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.mergeOwn([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.mergeOwn(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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 */\n var 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 */\n var _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 */\n var _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.
\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example Showing the difference with pairs:\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>}\n */\n var 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 */\n var _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.
\n * @example Showing the difference with values:\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 */\n var ownValues = _valuesFrom(keys);\n\n /**\n * Converts an object into an array of key / value pairs of its enumerable properties.
\n * See also {@link module:lamb.ownPairs|ownPairs} for picking only the own enumerable\n * properties and {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example\n * _.pairs({a: 1, b: 2, c: 3}) // => [[\"a\", 1], [\"b\", 2], [\"c\", 3]]\n *\n * @memberof module:lamb\n * @category Object\n * @function\n * @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>}\n */\n var pairs = _pairsFrom(enumerables);\n\n /**\n * Checks if the provided path exists in the given object.
\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 */\n function 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.
\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 */\n var pathExists = _makePartial3(pathExistsIn);\n\n /**\n * Builds a predicate that verifies if a condition is satisfied for the given\n * path in an object.
\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 */\n function 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.
\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 */\n function 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 A useful composition with mapWith:\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 */\n var pick = _curry2(pickIn, true);\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked\n * against the given predicate.
\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 */\n function 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 It's safe using it to swap keys:\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 */\n function 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 * keysMap 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 */\n var rename = _curry2(renameIn, true);\n\n /**\n * Uses the provided function as a keysMap generator and returns\n * a function expecting the object whose keys we want to {@link module:lamb.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 */\n function 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 */\n function _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.
\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.
\n * If the specified key is not part of the source object, it will be added to the\n * result.
\n * The main purpose of the function is to work on simple plain objects used as\n * data structures, such as JSON objects, and makes no effort to play nice with\n * objects created from an OOP perspective (it's not worth it).
\n * For example the prototype of the result will be Object's regardless\n * of the source's one.\n * @example\n * 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 */\n function 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 * key and value.
\n * The resulting function expects the object to act upon.
\n * Please refer to {@link module:lamb.setIn|setIn}'s description for explanations about\n * how the copy of the source object is made.\n * @example\n * 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 */\n var 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 */\n function _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.
\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 */\n function _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.
\n * The function will delegate the \"set action\" to {@link module:lamb.setIn|setIn} or\n * {@link module:lamb.setAt|setAt} depending on the value encountered in the path,\n * so please refer to the documentation of those functions for specifics about the\n * implementation.
\n * Note anyway that the distinction will be between Arrays, delegated\n * to {@link module:lamb.setAt|setAt}, and everything else (including array-like objects),\n * which will be delegated to {@link module:lamb.setIn|setIn}.
\n * As a result of that, array-like objects will be converted to objects having numbers as keys\n * and paths targeting non-object values will be converted to empty objects.
\n * You can anyway target array elements using integers in the path, even negative ones, but\n * the priority will be given to existing, and enumerable, object keys.
\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.
\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * 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 Targeting arrays:\n * _.setPathIn(user, \"status.scores.0\", 8) // => {id: 1, status: {active : false, scores: [8, 4, 6]}}\n *\n * // you can use negative indexes as well\n * _.setPathIn(user, \"status.scores.-1\", 8) // => {id: 1, status: {active : false, scores: [2, 4, 8]}}\n *\n * @example Arrays can also be part of the path and not necessarily its target:\n * 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 */\n function setPathIn (source, path, value, separator) {\n if (isNil(source)) {\n throw _makeTypeErrorFor(source, \"object\");\n }\n\n return _setPathIn(source, _toPathParts(path, separator), value);\n }\n\n /**\n * Builds a partial application of {@link module:lamb.setPathIn|setPathIn} expecting the\n * object to act upon.
\n * See {@link module:lamb.setPathIn|setPathIn} for more details and examples.\n * @example\n * 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 */\n function 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 */\n function 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 A useful composition with mapWith:\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 */\n var skip = _curry2(skipIn, true);\n\n /**\n * Builds a function expecting an object whose enumerable properties will be checked\n * against the given predicate.
\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 */\n var 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 */\n var _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.
\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}\n */\n var tear = _tearFrom(enumerables);\n\n /**\n * Same as {@link module:lamb.tear|tear}, but only the own properties of the object are\n * taken into account.\n * @example Showing the difference with tear:\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}\n */\n var 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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 Non-enumerable properties will be treated as non-existent:\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 */\n function 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 * key and updater, expecting the object to act upon.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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 */\n var 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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 Targeting arrays:\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 Arrays can also be part of the path and not necessarily its target:\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 */\n function updatePathIn (source, path, updater, separator) {\n var parts = _toPathParts(path, separator);\n var pathInfo = _getPathInfo(source, parts, false);\n\n if (pathInfo.isValid) {\n return _setPathIn(source, parts, updater(pathInfo.target));\n } else {\n return Array.isArray(source) ? slice(source, 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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 */\n function 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>} An array of errors in the form returned by\n * {@link module:lamb.checker|checker}, or an empty array.\n */\n function 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 */\n var validateWith = _curry2(validate, true);\n\n /**\n * Generates an array with the values of the enumerable properties of the given object.
\n * See also {@link module:lamb.ownValues|ownValues} 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 */\n var 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 */\n function _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 */\n function _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 */\n function padLeft (source, char, len) {\n return _getPadding(source, char, len) + source;\n }\n\n /**\n * Pads a string to the desired length with the given char starting from the end of the string.\n * @example\n * _.padRight(\"foo\", \"-\", 0) // => \"foo\"\n * _.padRight(\"foo\", \"-\", -1) // => \"foo\"\n * _.padRight(\"foo\", \"-\", 5) // => \"foo--\"\n * _.padRight(\"foo\", \"-\", 3) // => \"foo\"\n * _.padRight(\"foo\", \"ab\", 7) // => \"fooaaaa\"\n * _.padRight(\"foo\", \"\", 5) // => \"foo\"\n * _.padRight(\"\", \"-\", 5) // => \"-----\"\n *\n * @memberof module:lamb\n * @category String\n * @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 */\n function padRight (source, char, len) {\n return source + _getPadding(source, char, len);\n }\n\n /**\n * Builds a new string by repeating the source string the desired amount of times.
\n * Note that unlike the current ES6 proposal for\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 times 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 */\n function 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 [String.prototype.replace]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace}\n * with the given needle and substitution.
\n * Please refer to MDN docs for more insights and examples.\n * @example\n * const htmlString = \"

Lorem ipsum dolor sit amet

\";\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 [String.prototype.replace]{@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} (haystack: String) => String\n */\n var 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 */\n var 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 */\n var splitBy = _curry2(split, true);\n\n /**\n * A generic version of String.prototype.search\n * @private\n * @function\n * @param {String} s\n * @param {RegExp} pattern\n * @returns {Number}\n */\n var _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 */\n function 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.
\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 */\n function 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 */\n function isType (typeName) {\n return function (value) {\n return type(value) === typeName;\n };\n }\n\n exports.__ = __;\n exports.adapter = adapter;\n exports.add = add;\n exports.allOf = allOf;\n exports.always = always;\n exports.anyOf = anyOf;\n exports.append = append;\n exports.appendTo = appendTo;\n exports.application = application;\n exports.apply = apply;\n exports.applyTo = applyTo;\n exports.areSVZ = areSVZ;\n exports.areSame = areSame;\n exports.aritize = aritize;\n exports.asPartial = asPartial;\n exports.binary = binary;\n exports.casus = casus;\n exports.checker = checker;\n exports.clamp = clamp;\n exports.clampWithin = clampWithin;\n exports.collect = collect;\n exports.compose = compose;\n exports.condition = condition;\n exports.contains = contains;\n exports.count = count;\n exports.countBy = countBy;\n exports.curry = curry;\n exports.curryRight = curryRight;\n exports.curryable = curryable;\n exports.curryableRight = curryableRight;\n exports.debounce = debounce;\n exports.deduct = deduct;\n exports.difference = difference;\n exports.divide = divide;\n exports.divideBy = divideBy;\n exports.drop = drop;\n exports.dropFrom = dropFrom;\n exports.dropLastWhile = dropLastWhile;\n exports.dropWhile = dropWhile;\n exports.enumerables = enumerables;\n exports.every = every;\n exports.everyIn = everyIn;\n exports.filter = filter;\n exports.filterWith = filterWith;\n exports.find = find;\n exports.findIndex = findIndex;\n exports.findIndexWhere = findIndexWhere;\n exports.findLast = findLast;\n exports.findLastIndex = findLastIndex;\n exports.findLastIndexWhere = findLastIndexWhere;\n exports.findLastWhere = findLastWhere;\n exports.findWhere = findWhere;\n exports.flatMap = flatMap;\n exports.flatMapWith = flatMapWith;\n exports.flatten = flatten;\n exports.flip = flip;\n exports.forEach = forEach;\n exports.fromPairs = fromPairs;\n exports.generate = generate;\n exports.generic = generic;\n exports.getArgAt = getArgAt;\n exports.getAt = getAt;\n exports.getIn = getIn;\n exports.getIndex = getIndex;\n exports.getKey = getKey;\n exports.getPath = getPath;\n exports.getPathIn = getPathIn;\n exports.group = group;\n exports.groupBy = groupBy;\n exports.gt = gt;\n exports.gte = gte;\n exports.has = has;\n exports.hasKey = hasKey;\n exports.hasKeyValue = hasKeyValue;\n exports.hasOwn = hasOwn;\n exports.hasOwnKey = hasOwnKey;\n exports.hasPathValue = hasPathValue;\n exports.head = head;\n exports.identity = identity;\n exports.index = index;\n exports.indexBy = indexBy;\n exports.init = init;\n exports.insert = insert;\n exports.insertAt = insertAt;\n exports.intersection = intersection;\n exports.invoke = invoke;\n exports.invokeOn = invokeOn;\n exports.is = is;\n exports.isFinite = isFinite_;\n exports.isGT = isGT;\n exports.isGTE = isGTE;\n exports.isIn = isIn;\n exports.isInstanceOf = isInstanceOf;\n exports.isInteger = isInteger;\n exports.isLT = isLT;\n exports.isLTE = isLTE;\n exports.isNil = isNil;\n exports.isNull = isNull;\n exports.isSVZ = isSVZ;\n exports.isSafeInteger = isSafeInteger;\n exports.isType = isType;\n exports.isUndefined = isUndefined;\n exports.join = join;\n exports.joinWith = joinWith;\n exports.keySatisfies = keySatisfies;\n exports.keys = keys;\n exports.last = last;\n exports.list = list;\n exports.lt = lt;\n exports.lte = lte;\n exports.make = make;\n exports.map = map;\n exports.mapArgs = mapArgs;\n exports.mapValues = mapValues;\n exports.mapValuesWith = mapValuesWith;\n exports.mapWith = mapWith;\n exports.mean = mean;\n exports.median = median;\n exports.merge = merge;\n exports.mergeOwn = mergeOwn;\n exports.modulo = modulo;\n exports.multiply = multiply;\n exports.multiplyBy = multiplyBy;\n exports.not = not;\n exports.ownPairs = ownPairs;\n exports.ownValues = ownValues;\n exports.padLeft = padLeft;\n exports.padRight = padRight;\n exports.pairs = pairs;\n exports.partial = partial;\n exports.partialRight = partialRight;\n exports.partition = partition;\n exports.partitionWith = partitionWith;\n exports.pathExists = pathExists;\n exports.pathExistsIn = pathExistsIn;\n exports.pathSatisfies = pathSatisfies;\n exports.pick = pick;\n exports.pickIf = pickIf;\n exports.pickIn = pickIn;\n exports.pipe = pipe;\n exports.pluck = pluck;\n exports.pluckFrom = pluckFrom;\n exports.pull = pull;\n exports.pullFrom = pullFrom;\n exports.randomInt = randomInt;\n exports.range = range;\n exports.reduce = reduce;\n exports.reduceRight = reduceRight;\n exports.reduceRightWith = reduceRightWith;\n exports.reduceWith = reduceWith;\n exports.remainder = remainder;\n exports.rename = rename;\n exports.renameIn = renameIn;\n exports.renameWith = renameWith;\n exports.repeat = repeat;\n exports.replace = replace;\n exports.reverse = reverse;\n exports.rotate = rotate;\n exports.rotateBy = rotateBy;\n exports.setAt = setAt;\n exports.setIn = setIn;\n exports.setIndex = setIndex;\n exports.setKey = setKey;\n exports.setPath = setPath;\n exports.setPathIn = setPathIn;\n exports.shallowFlatten = shallowFlatten;\n exports.skip = skip;\n exports.skipIf = skipIf;\n exports.skipIn = skipIn;\n exports.slice = slice;\n exports.sliceAt = sliceAt;\n exports.some = some;\n exports.someIn = someIn;\n exports.sort = sort;\n exports.sortWith = sortWith;\n exports.sortedInsert = sortedInsert;\n exports.sorter = sorter;\n exports.sorterDesc = sorterDesc;\n exports.split = split;\n exports.splitBy = splitBy;\n exports.subtract = subtract;\n exports.sum = sum;\n exports.symmetricDifference = symmetricDifference;\n exports.tail = tail;\n exports.take = take;\n exports.takeFrom = takeFrom;\n exports.takeLastWhile = takeLastWhile;\n exports.takeWhile = takeWhile;\n exports.tapArgs = tapArgs;\n exports.tear = tear;\n exports.tearOwn = tearOwn;\n exports.testWith = testWith;\n exports.throttle = throttle;\n exports.transpose = transpose;\n exports.type = type;\n exports.unary = unary;\n exports.union = union;\n exports.unionBy = unionBy;\n exports.uniques = uniques;\n exports.uniquesBy = uniquesBy;\n exports.unless = unless;\n exports.updateAt = updateAt;\n exports.updateIn = updateIn;\n exports.updateIndex = updateIndex;\n exports.updateKey = updateKey;\n exports.updatePath = updatePath;\n exports.updatePathIn = updatePathIn;\n exports.validate = validate;\n exports.validateWith = validateWith;\n exports.values = values;\n exports.when = when;\n exports.zip = zip;\n exports.zipWithIndex = zipWithIndex;\n\n}));\n"]} \ No newline at end of file diff --git a/dist/lamb.min.mjs b/dist/lamb.min.mjs index d594893..d1647f9 100644 --- a/dist/lamb.min.mjs +++ b/dist/lamb.min.mjs @@ -5,4 +5,4 @@ * @module lamb * @license MIT */ -var n={};function r(n){return function(){return n}}function t(n,r){return n!=n?r!=r:n===r}function u(n){return function(r,t){return n.call(this,r,t)}}function e(n,r,t){return n=+n,(r=+r)>(t=+t)?NaN:nt?t:n}function i(r,t){return function(){if(!Array.isArray(t))return r.apply(this,arguments);for(var u,e=0,i=[],o=t.length,f=0;f>>0}function s(n,r){for(var t=0,u=h(n.length);t-1;a--)u=t[a],o[a]=u===n?arguments[e--]:u;for(a=0;a<=e;a++)f[a]=arguments[a];for(var c=0;cu&&(i=u);for(var o=i-e,f=o>0?Array(o):[],a=0;a0&&r-1 in Object(n)}function z(n){var r="function"==typeof Set,t=Array.isArray(n)?n:q(n)?R(n):[],u=r?new Set(t):null;this.add=function(n){return r?u.add(n):t.push(n),this},this.has=function(n){return r?u.has(n):E(t,n)}}function B(n,r){return new TypeError("Cannot convert "+F(n).toLowerCase()+" to "+r)}function G(n,r){for(var t=n.length,u=[],e=0;e=0&&u=0;f+=e)if(r(n[f],f,n)){o=f;break}return o}function un(n,r){return tn(n,r,!1)}function en(n,r){var t=un(n,r);return-1===t?void 0:n[t]}var on=d(un,!0);function fn(n,r){return tn(n,r,!0)}function an(n,r){var t=fn(n,r);return-1===t?void 0:n[t]}var cn=d(fn,!0),ln=d(an,!0),vn=d(en,!0);function hn(n,r){return S(n,(function(n,t,u,e){var i=r(t,u,e);Array.isArray(i)||(i=[i]);for(var o=0,f=i.length,a=n.length;o=-r&&nr||n!=n?1:-1),u}function tr(n,r,t){return"function"==typeof n&&n!==a||(n=null),"function"!=typeof t&&(t=rr),{isDescending:!0===r,compare:function(r,u){return n&&(r=n(r),u=n(u)),t(r,u)}}}function ur(n){return n&&"function"==typeof n.compare?n:tr(n)}function er(n){return n&&n.length?w(n,ur):[tr()]}function ir(n,r){for(var t=er(r),u=h(n.length),e=Array(u),i=0;i>1,o=t({value:r,index:i},{value:n[i],index:i});return e-u<=1?o<0?i:i+1:o<0?or(n,r,t,u,i):0===o?i+1:or(n,r,t,i,e)}function fr(n,r,t){var u=x(n,0,n.length);if(1===arguments.length)return u;var e=or(u,r,nr(er(t)),0,u.length);return u.splice(e,0,r),u}var ar=i(tr,[n,!1,n]),cr=i(tr,[n,!0,n]),lr=d(ir,!0);function vr(n,r){return K(n,r).concat(K(r,n))}var hr=U(1);function sr(n,r){return x(n,0,r)}var gr=d(sr,!0),pr=X(!0,!0),yr=X(!0,!1);function Ar(n){var r=l,t=h(n.length);if(0===t)return[];for(var u,e=0;e1&&u?o:1),a=Array(f),c=0;c=r?n.apply(this,t?a.reverse():a):Tr(n,r,t,u,a)}}function Dr(n,r){return function(t){return function(u){return function(e){return r?n.call(this,e,u,t):n.call(this,t,u,e)}}}}function Er(n,r,t,u){return r>>>0!==r&&(r=n.length),u&&r>1||r>3?Tr(n,r,t,u,[]):2===r?d(n,t):3===r?Dr(n,t):n}function Cr(n,r){return Er(n,r,!1)}function Ir(n,r){return Er(n,r,!1,!0)}function Lr(n,r){return Er(n,r,!0,!0)}function Pr(n,r){return Er(n,r,!0)}function Rr(n,r){var t;return function(){var u=arguments,e=function(){t=null,n.apply(this,u)}.bind(this);clearTimeout(t),t=setTimeout(e,r)}}function qr(n){return function(){var r=En.apply(null,arguments).reverse();return n.apply(this,r)}}function zr(n){return function(){return arguments[An(n,arguments.length)]}}function Br(n,r,t){var u=t[n];if("function"==typeof u){for(var e=r?h(r.length):0,i=e+arguments.length-3,o=Array(i),f=0;f=r&&(u=e,t=n.apply(this,arguments)),t}}function Ur(n){return function(r){return n.call(this,r)}}function Wr(n){if(!Array.isArray(n))throw B(n,"array");return function(){for(var r,t=n.length,u=0;ur}function tt(n,r){return n>=r}var ut=d($r),et=d(rt,!0),it=d(tt,!0);function ot(n,r){return n>>0;if(0===t)return NaN;var u=w(n,Number).sort(pt);if(t%2==0){var e=t/2;r=(u[e-1]+u[e])/2}else r=u[(t-1)/2];return r}function Nt(n,r){return n-r*Math.floor(n/r)}function Mt(n,r){return n*r}var xt=d(Mt,!0);function Vt(n,r){return Math.floor(Math.random()*(r-n+1)+n)}function kt(n){var r=+n;return r==r?r:0}function Ft(n,r,t){if(n=kt(n),r=kt(r),0===(t=3===arguments.length?kt(t):1))return r===n?[]:[n];for(var u=Math.max(Math.ceil((r-n)/t),0),e=Array(u),i=0,o=n;i=-e&&u(t=+t)?NaN:nt?t:n}function i(r,t){return function(){if(!Array.isArray(t))return r.apply(this,arguments);for(var u,e=0,i=[],o=t.length,f=0;f>>0}function s(n,r){for(var t=0,u=h(n.length);t-1;a--)u=t[a],o[a]=u===n?arguments[e--]:u;for(a=0;a<=e;a++)f[a]=arguments[a];for(var c=0;cu&&(i=u);for(var o=i-e,f=o>0?Array(o):[],a=0;a0&&r-1 in Object(n)}function z(n){var r="function"==typeof Set,t=Array.isArray(n)?n:q(n)?R(n):[],u=r?new Set(t):null;this.add=function(n){return r?u.add(n):t.push(n),this},this.has=function(n){return r?u.has(n):E(t,n)}}function B(n,r){return new TypeError("Cannot convert "+F(n).toLowerCase()+" to "+r)}function G(n,r){for(var t=n.length,u=[],e=0;e=0&&u=0;f+=e)if(r(n[f],f,n)){o=f;break}return o}function un(n,r){return tn(n,r,!1)}function en(n,r){var t=un(n,r);return-1===t?void 0:n[t]}var on=d(un,!0);function fn(n,r){return tn(n,r,!0)}function an(n,r){var t=fn(n,r);return-1===t?void 0:n[t]}var cn=d(fn,!0),ln=d(an,!0),vn=d(en,!0);function hn(n,r){return S(n,(function(n,t,u,e){var i=r(t,u,e);Array.isArray(i)||(i=[i]);for(var o=0,f=i.length,a=n.length;o=-r&&nr||n!=n?1:-1),u}function tr(n,r,t){return"function"==typeof n&&n!==a||(n=null),"function"!=typeof t&&(t=rr),{isDescending:!0===r,compare:function(r,u){return n&&(r=n(r),u=n(u)),t(r,u)}}}function ur(n){return n&&"function"==typeof n.compare?n:tr(n)}function er(n){return n&&n.length?w(n,ur):[tr()]}function ir(n,r){for(var t=er(r),u=h(n.length),e=Array(u),i=0;i>1,o=t({value:r,index:i},{value:n[i],index:i});return e-u<=1?o<0?i:i+1:o<0?or(n,r,t,u,i):0===o?i+1:or(n,r,t,i,e)}function fr(n,r,t){var u=x(n,0,n.length);if(1===arguments.length)return u;var e=or(u,r,nr(er(t)),0,u.length);return u.splice(e,0,r),u}var ar=i(tr,[n,!1,n]),cr=i(tr,[n,!0,n]),lr=d(ir,!0);function vr(n,r){return K(n,r).concat(K(r,n))}var hr=U(1);function sr(n,r){return x(n,0,r)}var gr=d(sr,!0),pr=X(!0,!0),yr=X(!0,!1);function Ar(n){var r=l,t=h(n.length);if(0===t)return[];for(var u,e=0;e1&&u?o:1),a=Array(f),c=0;c=r?n.apply(this,t?a.reverse():a):Tr(n,r,t,u,a)}}function Dr(n,r){return function(t){return function(u){return function(e){return r?n.call(this,e,u,t):n.call(this,t,u,e)}}}}function Er(n,r,t,u){return r>>>0!==r&&(r=n.length),u&&r>1||r>3?Tr(n,r,t,u,[]):2===r?d(n,t):3===r?Dr(n,t):n}function Cr(n,r){return Er(n,r,!1)}function Ir(n,r){return Er(n,r,!1,!0)}function Lr(n,r){return Er(n,r,!0,!0)}function Pr(n,r){return Er(n,r,!0)}function Rr(n,r){var t;return function(){var u=arguments,e=function(){t=null,n.apply(this,u)}.bind(this);clearTimeout(t),t=setTimeout(e,r)}}function qr(n){return function(){var r=En.apply(null,arguments).reverse();return n.apply(this,r)}}function zr(n){return function(){return arguments[An(n,arguments.length)]}}function Br(n,r,t){var u=t[n];if("function"==typeof u){for(var e=r?h(r.length):0,i=e+arguments.length-3,o=Array(i),f=0;f=r&&(u=e,t=n.apply(this,arguments)),t}}function Ur(n){return function(r){return n.call(this,r)}}function Wr(n){if(!Array.isArray(n))throw B(n,"array");return function(){for(var r,t=n.length,u=0;ur}function tt(n,r){return n>=r}var ut=d($r),et=d(rt,!0),it=d(tt,!0);function ot(n,r){return n>>0;if(0===t)return NaN;var u=w(n,Number).sort(pt);if(t%2==0){var e=t/2;r=(u[e-1]+u[e])/2}else r=u[(t-1)/2];return r}function Nt(n,r){return n-r*Math.floor(n/r)}function Mt(n,r){return n*r}var xt=d(Mt,!0);function Vt(n,r){return Math.floor(Math.random()*(r-n+1)+n)}function kt(n){var r=+n;return r==r?r:0}function Ft(n,r,t){if(n=kt(n),r=kt(r),0===(t=3===arguments.length?kt(t):1))return r===n?[]:[n];for(var u=Math.max(Math.ceil((r-n)/t),0),e=Array(u),i=0,o=n;i=-e&&u\n* @version 0.61.1-beta.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.
\n * With this comparison NaN is equal to itself, but 0 and -0 are\n * considered the same value.
\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.
\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.
\n * The function will convert to number all its parameters before starting any\n * evaluation, and will return NaN if min is greater\n * than max.\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.
\n * The {@link module:lamb.__|__} object can be used as a placeholder for arguments.
\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.
\n * The shouldAritize parameter is for the \"reduce\" functions, where\n * the absence of the initialValue 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 min\n * and a max 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 * 0 and 232 - 1 (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 iteratee for each element of the given array-like object.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example Adding a CSS class to all elements of a NodeList in a browser environment:\n * 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 null.\n * @example\n * _.isNull(null) // => true\n * _.isNull(void 0) // => false\n * _.isNull(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for undefined too.\n * @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 undefined.\n * @example\n * _.isUndefined(null) // => false\n * _.isUndefined(void 0) // => true\n * _.isUndefined(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for null too.\n * @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 null or undefined.\n * @example\n * _.isNil(NaN) // => false\n * _.isNil({}) // => false\n * _.isNil(null) // => true\n * _.isNil(void 0) // => true\n * _.isNil() // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNull|isNull}\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}.
\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.
\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.
\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.
\n * The difference is that the bound arguments will be appended to the ones received by\n * the resulting function.\n * @example\n * Explaining the difference with partial:\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 * Explaining placeholder substitutions:\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 step parameter must be 1\n * to build {@link module:lamb.reduce|reduce} and -1 to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\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 nCalls = len;\n result = initialValue;\n } else {\n if (len === 0) {\n throw new TypeError(\"Reduce of empty array-like with no initial value\");\n }\n\n result = arrayLike[idx];\n idx += step;\n nCalls = len - 1;\n }\n\n for (; nCalls--; idx += step) {\n result = accumulator(result, arrayLike[idx], idx, arrayLike);\n }\n\n return result;\n };\n}\n\n/**\n * Reduces (or folds) the values of an array-like object, starting from the first, to a new\n * value using the provided accumulator function.
\n * 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 accumulator and the optional initialValue 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.
\n * Note that unlike the native array method this function ensures that dense\n * arrays are returned.
\n * Also, unlike the native method, the start and end\n * parameters aren't optional and will be simply converted to integer.
\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 start and end bounds, builds a partial application\n * of {@link module:lamb.slice|slice} expecting the array-like object to slice.
\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.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * 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.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * 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 * iteratee, 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 predicate\n * test.
\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.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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.
\n * Note that this function uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 n elements of the given array or array-like object.\n * Note that, being this only a shortcut for a specific use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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.
\n * See the note and examples for {@link module:lamb.dropFrom|dropFrom} about passing a\n * negative n.\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.
\n * The function will stop calling the predicate as soon as it returns a falsy value.
\n * Note that an empty array-like will always produce a true result regardless of the\n * predicate because of [vacuous truth]{@link https://en.wikipedia.org/wiki/Vacuous_truth}.
\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 Showing the difference with Array.prototype.every:\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 -1 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 undefined 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 -1 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 undefined 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 Showing the difference with map:\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 Showing the difference with shallowFlatten:\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.
\n * Returns NaN 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.
\n * Like {@link module:lamb.slice|slice} the index can be negative.
\n * If the index isn't supplied, or if its value isn't an integer within the array-like bounds,\n * the function will return undefined.
\n * getIndex will throw an exception when receives null or\n * undefined in place of an array-like object, but returns undefined\n * for any other value.\n * @example\n * 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 Using negative indexes:\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 Adding a custom value for missing keys:\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.
\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.
\n * Should be used only when you're sure that your iteratee won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * 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 Result of an iteratee producing a duplicate key:\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.
\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.
\n * Negative indexes are allowed; when a negative index is out of bounds\n * the element will be inserted at the start of the resulting array.\n * @example\n * 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.
\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.
\n * Note that unlike the native method, this function won't convert\n * null and undefined values in the array to empty\n * strings and that the separator parameter isn't optional.
\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 Showing the differences with the native array method:\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.
\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.
\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.
\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.
\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}\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}.
\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.
\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 It's not the same as {@link module:lamb.difference|difference}:\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.
\n * The new function will create an array copy of the array-like without\n * the specified values.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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.
\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 accumulator and the optional initialValue 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}.
\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.
\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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 Using negative indexes:\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.
\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 Using a negative arity:\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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 Showing the difference with flatten:\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.
\n * The function will stop calling the predicate as soon as it returns a truthy value.
\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 Showing the difference with Array.prototype.some:\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.
\n * If the given values are of different types they\n * will be both converted to strings.
\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\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.
\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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used\n * in the comparison.
\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 Stable sort:\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 Stable multi-sort:\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 Using custom comparers:\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 With simple values:\n * _.sortedInsert([], 1) // => [1]\n * _.sortedInsert([2, 4, 6], 5) // => [2, 4, 5, 6]\n * _.sortedInsert([4, 2, 1], 3, _.sorterDesc()) // => [4, 3, 2, 1]\n *\n * @example With complex values:\n * 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 reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorterDesc|sorterDesc}\n * @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 reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}\n * @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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in\n * the comparison.
\n * See {@link module:lamb.sort|sort} for more examples.\n *\n * @example\n * var sortAsNumbers = _.sortWith([parseFloat]);\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * sortAsNumbers(weights) // => [\"1 Kg\", \"2 Kg\", \"7 Kg\", \"10 Kg\"]\n *\n * @memberof module:lamb\n * @category Array\n * @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}.
\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 n elements from an array or array-like object.
\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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.
\n * See the note and examples for {@link module:lamb.takeFrom|takeFrom} about passing a\n * negative n.\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.
\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example Transposing a matrix:\n * _.transpose([\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ]) // =>\n * // [\n * // [1, 4, 7],\n * // [2, 5, 8],\n * // [3, 6, 9]\n * // ]\n *\n * @example Showing the relationship with zip:\n * 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\n * @returns {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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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.
\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}\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>}\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.
\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.
\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.
\n * The final application will happen when one of the generated functions is\n * invoked without placeholders, using the parameters collected so far.
\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 Explaining the function's behaviour:\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 Exploiting optional parameters:\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 * collect.
\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 _currier function.
\n * If the desumed arity isn't greater than one, it will return the received\n * function itself, instead.\n * @private\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @param {Boolean} [isRightCurry=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.
\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.
\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.
\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call\n * happens immediately.\n * @example A common use case of debounce in a browser environment:\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.
\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.
\n * The resulting function will return undefined if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * 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 undefined otherwise.
\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 args,\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 * undefined.
\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.
\n * Returning undefined 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.
\n * See also {@link module:lamb.generic|generic} to create functions out of object methods.\n * @example Basic polymorphism with invoke:\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 With bound arguments:\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 undefined.\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.
\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.
\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-undefined value.
\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.
\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 * false 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 true 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.
\n * Note that this doesn't behave as the strict equality operator, but rather as a shim of ES6's\n * [Object.is]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is}.\n * Differences are that 0 and -0 aren't the same value and, finally,\n * NaN is equal to itself.
\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}.
\n * The function will apply the received arguments to fn if the predicate is satisfied\n * with the same arguments, otherwise will return undefined.
\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 trueFn,\n * if the predicate is satisfied with the same arguments, or to falseFn otherwise.
\n * Although you can use other conditions as trueFn or falseFn,\n * it's probably better to use {@link module:lamb.adapter|adapter} to build more complex behaviours.
\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.
\n * Wraps the native > 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 * >= operator, so -0 === 0.\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}.
\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.
\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}.
\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}.
\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.
\n * Wraps the native < 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}.
\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 * <= operator, so -0 === 0.\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}.
\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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.when|when} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its trueFn 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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.unless|unless} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its falseFn 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.
\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 true 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 true 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 -(253 - 1) inclusive to\n * 253 - 1 inclusive.
\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 true 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 randomInt(0.1, 1.2) could be 2.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @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 start up to,\n * but not including, limit, using the given step.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(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 Behaviour if step happens to be zero:\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.
\n * The path is a string with property names separated by dots by default, but\n * it can be customised with the optional third parameter.
\n * You can use integers in the path, even negative ones, to refer to array-like\n * object indexes, but the priority will be given to existing object keys:\n * the last example explains this particular case.\n * @example\n * 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 Accessing array-like objects indexes:\n * _.getPathIn(user, \"login.password.1\") // => \"b\"\n * _.getPathIn(user, \"scores.0\") // => {id: 1, value: 10}\n * _.getPathIn(user, \"scores.-1.value\") // => 30\n *\n * @example Priority will be given to existing object keys over indexes:\n * _.getPathIn(user, \"scores.-1\") // => {id: 3, value: 30}\n *\n * // let's do something funny\n * user.scores[\"-1\"] = \"foo bar\";\n *\n * _.getPathIn(user, \"scores.-1\") // => \"foo bar\";\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPath|getPath}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @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 checker function meant to be used with\n * {@link module:lamb.validate|validate}.
\n * Note that the function accepts multiple keyPaths as a means to\n * compare their values. In other words all the received keyPaths will be\n * passed as arguments to the predicate to run the test.
\n * If you want to run the same single property check with multiple properties, you should build\n * multiple checkers and combine them with {@link module:lamb.validate|validate}.\n * @example\n * 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 * [\"message\", [\"propertyA\", \"propertyB\"]] 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 Showing the difference with {@link module:lamb.keys|keys}:\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}.
\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>} 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.
\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}.
\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.
\n * @example Comparison with has:\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}.
\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.
\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.
\n * The value check is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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 Object.keys.\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.
\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.
\n * This function shims the ECMAScript 6 version, by forcing a conversion to\n * object for any value but null and undefined.\n * @example Showing the difference with {@link module:lamb.enumerables|enumerables}:\n * 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.
\n * If the list of keys is longer than the values one, the keys will be created with\n * undefined values.
\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}.
\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.
\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.merge([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.merge(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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 Showing the difference with merge:\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.mergeOwn([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.mergeOwn(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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.
\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example Showing the difference with pairs:\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>}\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.
\n * @example Showing the difference with values:\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.
\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>}\n */\nvar pairs = _pairsFrom(enumerables);\n\n/**\n * Checks if the provided path exists in the given object.
\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.
\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.
\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.
\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 A useful composition with mapWith:\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.
\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 It's safe using it to swap keys:\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 * keysMap 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 keysMap 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.
\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.
\n * If the specified key is not part of the source object, it will be added to the\n * result.
\n * The main purpose of the function is to work on simple plain objects used as\n * data structures, such as JSON objects, and makes no effort to play nice with\n * objects created from an OOP perspective (it's not worth it).
\n * For example the prototype of the result will be Object's regardless\n * of the source's one.\n * @example\n * 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 * key and value.
\n * The resulting function expects the object to act upon.
\n * Please refer to {@link module:lamb.setIn|setIn}'s description for explanations about\n * how the copy of the source object is made.\n * @example\n * 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.
\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.
\n * The function will delegate the \"set action\" to {@link module:lamb.setIn|setIn} or\n * {@link module:lamb.setAt|setAt} depending on the value encountered in the path,\n * so please refer to the documentation of those functions for specifics about the\n * implementation.
\n * Note anyway that the distinction will be between Arrays, delegated\n * to {@link module:lamb.setAt|setAt}, and everything else (including array-like objects),\n * which will be delegated to {@link module:lamb.setIn|setIn}.
\n * As a result of that, array-like objects will be converted to objects having numbers as keys\n * and paths targeting non-object values will be converted to empty objects.
\n * You can anyway target array elements using integers in the path, even negative ones, but\n * the priority will be given to existing, and enumerable, object keys.
\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.
\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * 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 Targeting arrays:\n * _.setPathIn(user, \"status.scores.0\", 8) // => {id: 1, status: {active : false, scores: [8, 4, 6]}}\n *\n * // you can use negative indexes as well\n * _.setPathIn(user, \"status.scores.-1\", 8) // => {id: 1, status: {active : false, scores: [2, 4, 8]}}\n *\n * @example Arrays can also be part of the path and not necessarily its target:\n * 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.
\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 A useful composition with mapWith:\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.
\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.
\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}\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 Showing the difference with tear:\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}\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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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 Non-enumerable properties will be treated as non-existent:\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 * key and updater, expecting the object to act upon.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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 Targeting arrays:\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 Arrays can also be part of the path and not necessarily its target:\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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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>} 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.
\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.
\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 times 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 [String.prototype.replace]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace}\n * with the given needle and substitution.
\n * Please refer to MDN docs for more insights and examples.\n * @example\n * const htmlString = \"

Lorem ipsum dolor sit amet

\";\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 [String.prototype.replace]{@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} (haystack: String) => String\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 String.prototype.search\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.
\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"]} \ No newline at end of file +{"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 \n* @version 0.61.1-beta.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.
\n * With this comparison NaN is equal to itself, but 0 and -0 are\n * considered the same value.
\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.
\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.
\n * The function will convert to number all its parameters before starting any\n * evaluation, and will return NaN if min is greater\n * than max.\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.
\n * The {@link module:lamb.__|__} object can be used as a placeholder for arguments.
\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.
\n * The shouldAritize parameter is for the \"reduce\" functions, where\n * the absence of the initialValue 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 min\n * and a max 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 * 0 and 232 - 1 (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 iteratee for each element of the given array-like object.
\n * Note that unlike the native array method this function doesn't skip unassigned or deleted indexes.\n * @example Adding a CSS class to all elements of a NodeList in a browser environment:\n * 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 null.\n * @example\n * _.isNull(null) // => true\n * _.isNull(void 0) // => false\n * _.isNull(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for undefined too.\n * @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 undefined.\n * @example\n * _.isUndefined(null) // => false\n * _.isUndefined(void 0) // => true\n * _.isUndefined(false) // => false\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNil|isNil} if you want to check for null too.\n * @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 null or undefined.\n * @example\n * _.isNil(NaN) // => false\n * _.isNil({}) // => false\n * _.isNil(null) // => true\n * _.isNil(void 0) // => true\n * _.isNil() // => true\n *\n * @memberof module:lamb\n * @category Type\n * @see {@link module:lamb.isNull|isNull}\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}.
\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.
\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.
\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.
\n * The difference is that the bound arguments will be appended to the ones received by\n * the resulting function.\n * @example\n * Explaining the difference with partial:\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 * Explaining placeholder substitutions:\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 step parameter must be 1\n * to build {@link module:lamb.reduce|reduce} and -1 to build\n * {@link module:lamb.reduceRight|reduceRight}.\n * @private\n * @param {Number} step\n * @returns {Function}\n */\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 accumulator function.
\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 accumulator and the optional initialValue 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.
\n * Note that unlike the native array method this function ensures that dense\n * arrays are returned.
\n * Also, unlike the native method, the start and end\n * parameters aren't optional and will be simply converted to integer.
\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 start and end bounds, builds a partial application\n * of {@link module:lamb.slice|slice} expecting the array-like object to slice.
\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.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.contains|contains} for a curried version building a predicate.\n * @example\n * 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.
\n * Please note that the equality test is made with {@link module:lamb.areSVZ|areSVZ}; so you can\n * check for NaN, but 0 and -0 are the same value.
\n * See also {@link module:lamb.isIn|isIn} for an uncurried version.\n * @example\n * 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 * iteratee, 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 predicate\n * test.
\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.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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.
\n * Note that this function uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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 n elements of the given array or array-like object.\n * Note that, being this only a shortcut for a specific use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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.
\n * See the note and examples for {@link module:lamb.dropFrom|dropFrom} about passing a\n * negative n.\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.
\n * The function will stop calling the predicate as soon as it returns a falsy value.
\n * Note that an empty array-like will always produce a true result regardless of the\n * predicate because of [vacuous truth]{@link https://en.wikipedia.org/wiki/Vacuous_truth}.
\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 Showing the difference with Array.prototype.every:\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 -1 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 undefined 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 -1 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 undefined 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 Showing the difference with map:\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 Showing the difference with shallowFlatten:\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.
\n * Returns NaN 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.
\n * Like {@link module:lamb.slice|slice} the index can be negative.
\n * If the index isn't supplied, or if its value isn't an integer within the array-like bounds,\n * the function will return undefined.
\n * getIndex will throw an exception when receives null or\n * undefined in place of an array-like object, but returns undefined\n * for any other value.\n * @example\n * 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 Using negative indexes:\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 Adding a custom value for missing keys:\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.
\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.
\n * Should be used only when you're sure that your iteratee won't produce\n * duplicate keys, otherwise only the last evaluated element will be in the result.\n * @example\n * 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 Result of an iteratee producing a duplicate key:\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.
\n * If the index is greater than the length of the array-like, the element\n * will be appended at the end.
\n * Negative indexes are allowed; when a negative index is out of bounds\n * the element will be inserted at the start of the resulting array.\n * @example\n * 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.
\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.
\n * Note that unlike the native method, this function won't convert\n * null and undefined values in the array to empty\n * strings and that the separator parameter isn't optional.
\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 Showing the differences with the native array method:\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.
\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.
\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.
\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.
\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}\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}.
\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.
\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 It's not the same as {@link module:lamb.difference|difference}:\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.
\n * The new function will create an array copy of the array-like without\n * the specified values.
\n * The equality test is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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.
\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 accumulator and the optional initialValue 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}.
\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.
\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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 Using negative indexes:\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.
\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 Using a negative arity:\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.
\n * If the index is not an integer or if it's out of bounds, the function\n * will return a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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 Showing the difference with flatten:\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.
\n * The function will stop calling the predicate as soon as it returns a truthy value.
\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 Showing the difference with Array.prototype.some:\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.
\n * If the given values are of different types they\n * will be both converted to strings.
\n * Uses the SameValueZero comparison.\n * @private\n * @param {*} a\n * @param {*} b\n * @returns {Number} -1 | 0 | 1\n */\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.
\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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used\n * in the comparison.
\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 Stable sort:\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 Stable multi-sort:\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 Using custom comparers:\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 With simple values:\n * _.sortedInsert([], 1) // => [1]\n * _.sortedInsert([2, 4, 6], 5) // => [2, 4, 5, 6]\n * _.sortedInsert([4, 2, 1], 3, _.sorterDesc()) // => [4, 3, 2, 1]\n *\n * @example With complex values:\n * 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 reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorterDesc|sorterDesc}\n * @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 reader and\n * comparer.
\n * See {@link module:lamb.sort|sort} for various examples.\n *\n * @memberof module:lamb\n * @category Array\n * @function\n * @see {@link module:lamb.sortedInsert|sortedInsert}\n * @see {@link module:lamb.sort|sort}, {@link module:lamb.sortWith|sortWith}\n * @see {@link module:lamb.sorter|sorter}\n * @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.
\n * A \"reader\" is a function that evaluates the array element and supplies the value to be used in\n * the comparison.
\n * See {@link module:lamb.sort|sort} for more examples.\n *\n * @example\n * var sortAsNumbers = _.sortWith([parseFloat]);\n * var weights = [\"2 Kg\", \"10 Kg\", \"1 Kg\", \"7 Kg\"];\n *\n * sortAsNumbers(weights) // => [\"1 Kg\", \"2 Kg\", \"7 Kg\", \"10 Kg\"]\n *\n * @memberof module:lamb\n * @category Array\n * @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}.
\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 n elements from an array or array-like object.
\n * Note that, being this a shortcut for a common use case of {@link module:lamb.slice|slice},\n * n can be a negative number.\n * @example\n * 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.
\n * See the note and examples for {@link module:lamb.takeFrom|takeFrom} about passing a\n * negative n.\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.
\n * Just like {@link module:lamb.zip|zip}, the received array-like objects will be truncated to the\n * shortest length.\n * @example Transposing a matrix:\n * _.transpose([\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ]) // =>\n * // [\n * // [1, 4, 7],\n * // [2, 5, 8],\n * // [3, 6, 9]\n * // ]\n *\n * @example Showing the relationship with zip:\n * 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\n * @returns {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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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.
\n * Uses the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}\n * to test the equality of values.
\n * When two values are considered equal, the first occurence will be the one included\n * in the result array.
\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.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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.
\n * If the index is not an integer or if it's out of bounds, the function will return\n * a copy of the original array.
\n * Negative indexes are allowed.\n * @example\n * 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.
\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}\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>}\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.
\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.
\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.
\n * The final application will happen when one of the generated functions is\n * invoked without placeholders, using the parameters collected so far.
\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 Explaining the function's behaviour:\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 Exploiting optional parameters:\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 * collect.
\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 _currier function.
\n * If the desumed arity isn't greater than one, it will return the received\n * function itself, instead.\n * @private\n * @param {Function} fn\n * @param {Number} [arity=fn.length]\n * @param {Boolean} [isRightCurry=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.
\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.
\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.
\n * See also {@link module:lamb.throttle|throttle} for a different behaviour where the first call\n * happens immediately.\n * @example A common use case of debounce in a browser environment:\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.
\n * As with {@link module:lamb.getAt|getAt} negative indexes are allowed.
\n * The resulting function will return undefined if no arguments are\n * passed or if the index is out of bounds.\n * @example\n * 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 undefined otherwise.
\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 args,\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 * undefined.
\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.
\n * Returning undefined 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.
\n * See also {@link module:lamb.generic|generic} to create functions out of object methods.\n * @example Basic polymorphism with invoke:\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 With bound arguments:\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 undefined.\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.
\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.
\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-undefined value.
\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.
\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 * false 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 true 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.
\n * Note that this doesn't behave as the strict equality operator, but rather as a shim of ES6's\n * [Object.is]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is}.\n * Differences are that 0 and -0 aren't the same value and, finally,\n * NaN is equal to itself.
\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}.
\n * The function will apply the received arguments to fn if the predicate is satisfied\n * with the same arguments, otherwise will return undefined.
\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 trueFn,\n * if the predicate is satisfied with the same arguments, or to falseFn otherwise.
\n * Although you can use other conditions as trueFn or falseFn,\n * it's probably better to use {@link module:lamb.adapter|adapter} to build more complex behaviours.
\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.
\n * Wraps the native > 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 * >= operator, so -0 === 0.\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}.
\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.
\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}.
\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}.
\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.
\n * Wraps the native < 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}.
\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 * <= operator, so -0 === 0.\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}.
\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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.when|when} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its trueFn 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 fn function will be\n * applied to the same value. The received argument is returned as it is otherwise.
\n * See {@link module:lamb.unless|unless} for the opposite behaviour.
\n * It's a shortcut for a common use case of {@link module:lamb.condition|condition},\n * where its falseFn 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.
\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 true 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 true 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 -(253 - 1) inclusive to\n * 253 - 1 inclusive.
\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 true 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 randomInt(0.1, 1.2) could be 2.\n * @example\n *\n * _.randomInt(1, 10) // => an integer >=1 && <= 10\n *\n * @memberof module:lamb\n * @category Math\n * @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 start up to,\n * but not including, limit, using the given step.\n * @example\n * _.range(2, 10) // => [2, 3, 4, 5, 6, 7, 8, 9]\n * _.range(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 Behaviour if step happens to be zero:\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.
\n * The path is a string with property names separated by dots by default, but\n * it can be customised with the optional third parameter.
\n * You can use integers in the path, even negative ones, to refer to array-like\n * object indexes, but the priority will be given to existing object keys:\n * the last example explains this particular case.\n * @example\n * 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 Accessing array-like objects indexes:\n * _.getPathIn(user, \"login.password.1\") // => \"b\"\n * _.getPathIn(user, \"scores.0\") // => {id: 1, value: 10}\n * _.getPathIn(user, \"scores.-1.value\") // => 30\n *\n * @example Priority will be given to existing object keys over indexes:\n * _.getPathIn(user, \"scores.-1\") // => {id: 3, value: 30}\n *\n * // let's do something funny\n * user.scores[\"-1\"] = \"foo bar\";\n *\n * _.getPathIn(user, \"scores.-1\") // => \"foo bar\";\n *\n * @memberof module:lamb\n * @category Object\n * @see {@link module:lamb.getPath|getPath}\n * @see {@link module:lamb.getIn|getIn}, {@link module:lamb.getKey|getKey}\n * @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 checker function meant to be used with\n * {@link module:lamb.validate|validate}.
\n * Note that the function accepts multiple keyPaths as a means to\n * compare their values. In other words all the received keyPaths will be\n * passed as arguments to the predicate to run the test.
\n * If you want to run the same single property check with multiple properties, you should build\n * multiple checkers and combine them with {@link module:lamb.validate|validate}.\n * @example\n * 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 * [\"message\", [\"propertyA\", \"propertyB\"]] 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 Showing the difference with {@link module:lamb.keys|keys}:\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}.
\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>} 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.
\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}.
\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.
\n * @example Comparison with has:\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}.
\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.
\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.
\n * The value check is made with the [\"SameValueZero\" comparison]{@link module:lamb.areSVZ|areSVZ}.
\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 Object.keys.\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.
\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.
\n * This function shims the ECMAScript 6 version, by forcing a conversion to\n * object for any value but null and undefined.\n * @example Showing the difference with {@link module:lamb.enumerables|enumerables}:\n * 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.
\n * If the list of keys is longer than the values one, the keys will be created with\n * undefined values.
\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}.
\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.
\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.merge([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.merge(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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 Showing the difference with merge:\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 Array-like objects will be transformed to objects with numbers as keys:\n * _.mergeOwn([1, 2], {a: 2}) // => {\"0\": 1, \"1\": 2, a: 2}\n * _.mergeOwn(\"foo\", {a: 2}) // => {\"0\": \"f\", \"1\": \"o\", \"2\": \"o\", a: 2}\n *\n * @example Every other non-nil value will be treated as an empty object:\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.
\n * See also {@link module:lamb.fromPairs|fromPairs} for the reverse operation.\n * @example Showing the difference with pairs:\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>}\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.
\n * @example Showing the difference with values:\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.
\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>}\n */\nvar pairs = _pairsFrom(enumerables);\n\n/**\n * Checks if the provided path exists in the given object.
\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.
\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.
\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.
\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 A useful composition with mapWith:\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.
\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 It's safe using it to swap keys:\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 * keysMap 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 keysMap 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.
\n * All the remaining enumerable keys of the source object will be simply copied in the\n * result object without breaking references.
\n * If the specified key is not part of the source object, it will be added to the\n * result.
\n * The main purpose of the function is to work on simple plain objects used as\n * data structures, such as JSON objects, and makes no effort to play nice with\n * objects created from an OOP perspective (it's not worth it).
\n * For example the prototype of the result will be Object's regardless\n * of the source's one.\n * @example\n * 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 * key and value.
\n * The resulting function expects the object to act upon.
\n * Please refer to {@link module:lamb.setIn|setIn}'s description for explanations about\n * how the copy of the source object is made.\n * @example\n * 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.
\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.
\n * The function will delegate the \"set action\" to {@link module:lamb.setIn|setIn} or\n * {@link module:lamb.setAt|setAt} depending on the value encountered in the path,\n * so please refer to the documentation of those functions for specifics about the\n * implementation.
\n * Note anyway that the distinction will be between Arrays, delegated\n * to {@link module:lamb.setAt|setAt}, and everything else (including array-like objects),\n * which will be delegated to {@link module:lamb.setIn|setIn}.
\n * As a result of that, array-like objects will be converted to objects having numbers as keys\n * and paths targeting non-object values will be converted to empty objects.
\n * You can anyway target array elements using integers in the path, even negative ones, but\n * the priority will be given to existing, and enumerable, object keys.
\n * Non-enumerable properties encountered in the path will be considered as non-existent properties.
\n * Like {@link module:lamb.getPathIn|getPathIn} or {@link module:lamb.getPath|getPath} you can\n * use custom path separators.\n * @example\n * 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 Targeting arrays:\n * _.setPathIn(user, \"status.scores.0\", 8) // => {id: 1, status: {active : false, scores: [8, 4, 6]}}\n *\n * // you can use negative indexes as well\n * _.setPathIn(user, \"status.scores.-1\", 8) // => {id: 1, status: {active : false, scores: [2, 4, 8]}}\n *\n * @example Arrays can also be part of the path and not necessarily its target:\n * 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.
\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 A useful composition with mapWith:\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.
\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.
\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}\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 Showing the difference with tear:\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}\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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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 Non-enumerable properties will be treated as non-existent:\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 * key and updater, expecting the object to act upon.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setIn|setIn}; a copy of the\n * source is returned otherwise.\n * @example\n * 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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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 Targeting arrays:\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 Arrays can also be part of the path and not necessarily its target:\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.
\n * This function is meant for updating existing enumerable properties, and for those it\n * will delegate the \"set action\" to {@link module:lamb.setPathIn|setPathIn}; a copy of the\n * source is returned otherwise.
\n * Like the other \"path\" functions, negative indexes can be used to access array elements, but\n * the priority will be given to existing, and enumerable, object keys.\n * @example\n * 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>} 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.
\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.
\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 times 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 [String.prototype.replace]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace}\n * with the given needle and substitution.
\n * Please refer to MDN docs for more insights and examples.\n * @example\n * const htmlString = \"

Lorem ipsum dolor sit amet

\";\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 [String.prototype.replace]{@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} (haystack: String) => String\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 String.prototype.search\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.
\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"]} \ No newline at end of file diff --git a/dist/lamb.mjs b/dist/lamb.mjs index 45d6c42..e8141a2 100644 --- a/dist/lamb.mjs +++ b/dist/lamb.mjs @@ -574,10 +574,7 @@ function _makeReducer (step) { var nCalls; var result; - if (arguments.length === 3) { - nCalls = len; - result = initialValue; - } else { + if (arguments.length < 3) { if (len === 0) { throw new TypeError("Reduce of empty array-like with no initial value"); } @@ -585,6 +582,9 @@ function _makeReducer (step) { result = arrayLike[idx]; idx += step; nCalls = len - 1; + } else { + nCalls = len; + result = initialValue; } for (; nCalls--; idx += step) { diff --git a/src/array/__tests__/reduceRight.spec.js b/src/array/__tests__/reduceRight.spec.js index 92cb115..9ee883f 100644 --- a/src/array/__tests__/reduceRight.spec.js +++ b/src/array/__tests__/reduceRight.spec.js @@ -1,4 +1,5 @@ import identity from "../../core/identity"; +import mapValuesWith from "../../object/mapValuesWith"; import reduceRight from "../reduceRight"; import reduceRightWith from "../reduceRightWith"; import subtract from "../../math/subtract"; @@ -63,6 +64,13 @@ describe("reduceRight / reduceRightWith", () => { expect(sumMock).toHaveBeenCalledTimes(6); }); + it("should use all the necessary arguments even if reduce is called with more than three arguements", () => { + // causes reduce to be called with five arguments + const f = mapValuesWith(reduceRightWith(sum, 7)); + + expect(f({ a: [...arr] }).a).toBe(22); + }); + it("should build a function throwing an exception if the accumulator isn't a function or is missing", () => { nonFunctions.forEach(value => { expect(() => { reduceRight(arr, value, 0); }).toThrow(); diff --git a/src/core/__tests__/reduce.spec.js b/src/core/__tests__/reduce.spec.js index 866d378..3c67a48 100644 --- a/src/core/__tests__/reduce.spec.js +++ b/src/core/__tests__/reduce.spec.js @@ -1,4 +1,5 @@ import identity from "../identity"; +import mapValuesWith from "../../object/mapValuesWith"; import reduce from "../reduce"; import reduceWith from "../reduceWith"; import subtract from "../../math/subtract"; @@ -63,6 +64,13 @@ describe("reduce / reduceWith", () => { expect(sumMock).toHaveBeenCalledTimes(6); }); + it("should use all the necessary arguments even if reduce is called with more than three arguements", () => { + // causes reduce to be called with five arguments + const f = mapValuesWith(reduceWith(sum, 7)); + + expect(f({ a: [...arr] }).a).toBe(22); + }); + it("should build a function throwing an exception if the accumulator isn't a function or is missing", () => { nonFunctions.forEach(value => { expect(() => { reduce(arr, value, 0); }).toThrow(); diff --git a/src/privates/_makeReducer.js b/src/privates/_makeReducer.js index 7c3c65c..e3802dc 100644 --- a/src/privates/_makeReducer.js +++ b/src/privates/_makeReducer.js @@ -15,10 +15,7 @@ function _makeReducer (step) { var nCalls; var result; - if (arguments.length === 3) { - nCalls = len; - result = initialValue; - } else { + if (arguments.length < 3) { if (len === 0) { throw new TypeError("Reduce of empty array-like with no initial value"); } @@ -26,6 +23,9 @@ function _makeReducer (step) { result = arrayLike[idx]; idx += step; nCalls = len - 1; + } else { + nCalls = len; + result = initialValue; } for (; nCalls--; idx += step) {