Built motion from commit 1038d87.|0.0.141
[motion.git] / public / bower_components / lodash / dist / lodash.core.js
index 73b541b..2c541fb 100644 (file)
@@ -1,11 +1,11 @@
 /**
  * @license
- * lodash 4.11.2 (Custom Build) <https://lodash.com/>
+ * lodash 4.5.1 (Custom Build) <https://lodash.com/>
  * Build: `lodash core -o ./dist/lodash.core.js`
- * Copyright jQuery Foundation and other contributors <https://jquery.org/>
- * Released under MIT license <https://lodash.com/license>
+ * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
  * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
- * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <https://lodash.com/license>
  */
 ;(function() {
 
   var undefined;
 
   /** Used as the semantic version number. */
-  var VERSION = '4.11.2';
-
-  /** Used as the `TypeError` message for "Functions" methods. */
-  var FUNC_ERROR_TEXT = 'Expected a function';
+  var VERSION = '4.5.1';
 
   /** Used to compose bitmasks for wrapper metadata. */
   var BIND_FLAG = 1,
@@ -26,6 +23,9 @@
   var UNORDERED_COMPARE_FLAG = 1,
       PARTIAL_COMPARE_FLAG = 2;
 
+  /** Used as the `TypeError` message for "Functions" methods. */
+  var FUNC_ERROR_TEXT = 'Expected a function';
+
   /** Used as references for various `Number` constants. */
   var INFINITY = 1 / 0,
       MAX_SAFE_INTEGER = 9007199254740991;
    * @returns {Array} Returns `array`.
    */
   function arrayPush(array, values) {
-    array.push.apply(array, values);
+    var index = -1,
+        length = values.length,
+        offset = array.length;
+
+    while (++index < length) {
+      array[offset + index] = values[index];
+    }
     return array;
   }
 
   /**
+   * The base implementation of methods like `_.max` and `_.min` which accepts a
+   * `comparator` to determine the extremum value.
+   *
+   * @private
+   * @param {Array} array The array to iterate over.
+   * @param {Function} iteratee The iteratee invoked per iteration.
+   * @param {Function} comparator The comparator used to compare values.
+   * @returns {*} Returns the extremum value.
+   */
+  function baseExtremum(array, iteratee, comparator) {
+    var index = -1,
+        length = array.length;
+
+    while (++index < length) {
+      var value = array[index],
+          current = iteratee(value);
+
+      if (current != null && (computed === undefined
+            ? current === current
+            : comparator(current, computed)
+          )) {
+        var computed = current,
+            result = value;
+      }
+    }
+    return result;
+  }
+
+  /**
    * The base implementation of methods like `_.find` and `_.findKey`, without
    * support for iteratee shorthands, which iterates over `collection` using
    * `eachFunc`.
    * @param {Array|Object} collection The collection to search.
    * @param {Function} predicate The function invoked per iteration.
    * @param {Function} eachFunc The function to iterate over `collection`.
-   * @param {boolean} [retKey] Specify returning the key of the found element
-   *  instead of the element itself.
+   * @param {boolean} [retKey] Specify returning the key of the found element instead of the element itself.
    * @returns {*} Returns the found element or its key, else `undefined`.
    */
   function baseFind(collection, predicate, eachFunc, retKey) {
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @param {*} accumulator The initial value.
-   * @param {boolean} initAccum Specify using the first or last element of
-   *  `collection` as the initial value.
+   * @param {boolean} initAccum Specify using the first or last element of `collection` as the initial value.
    * @param {Function} eachFunc The function to iterate over `collection`.
    * @returns {*} Returns the accumulated value.
    */
   }
 
   /**
+   * Compares values to sort them in ascending order.
+   *
+   * @private
+   * @param {*} value The value to compare.
+   * @param {*} other The other value to compare.
+   * @returns {number} Returns the sort order indicator for `value`.
+   */
+  function compareAscending(value, other) {
+    if (value !== other) {
+      var valIsNull = value === null,
+          valIsUndef = value === undefined,
+          valIsReflexive = value === value;
+
+      var othIsNull = other === null,
+          othIsUndef = other === undefined,
+          othIsReflexive = other === other;
+
+      if ((value > other && !othIsNull) || !valIsReflexive ||
+          (valIsNull && !othIsUndef && othIsReflexive) ||
+          (valIsUndef && othIsReflexive)) {
+        return 1;
+      }
+      if ((value < other && !valIsNull) || !othIsReflexive ||
+          (othIsNull && !valIsUndef && valIsReflexive) ||
+          (othIsUndef && valIsReflexive)) {
+        return -1;
+      }
+    }
+    return 0;
+  }
+
+  /**
    * Used by `_.escape` to convert characters to HTML entities.
    *
    * @private
   }
 
   /**
+   * Checks if `value` is a valid array-like index.
+   *
+   * @private
+   * @param {*} value The value to check.
+   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+   */
+  function isIndex(value, length) {
+    value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
+    length = length == null ? MAX_SAFE_INTEGER : length;
+    return value > -1 && value % 1 == 0 && value < length;
+  }
+
+  /**
    * Converts `iterator` to an array.
    *
    * @private
   var idCounter = 0;
 
   /**
-   * Used to resolve the
-   * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+   * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
    * of values.
    */
   var objectToString = objectProto.toString;
 
   /**
    * Creates a `lodash` object which wraps `value` to enable implicit method
-   * chain sequences. Methods that operate on and return arrays, collections,
-   * and functions can be chained together. Methods that retrieve a single value
-   * or may return a primitive value will automatically end the chain sequence
-   * and return the unwrapped value. Otherwise, the value must be unwrapped
-   * with `_#value`.
+   * chaining. Methods that operate on and return arrays, collections, and
+   * functions can be chained together. Methods that retrieve a single value or
+   * may return a primitive value will automatically end the chain sequence and
+   * return the unwrapped value. Otherwise, the value must be unwrapped with
+   * `_#value`.
    *
-   * Explicit chain sequences, which must be unwrapped with `_#value`, may be
-   * enabled using `_.chain`.
+   * Explicit chaining, which must be unwrapped with `_#value` in all cases,
+   * may be enabled using `_.chain`.
    *
    * The execution of chained methods is lazy, that is, it's deferred until
    * `_#value` is implicitly or explicitly called.
    *
-   * Lazy evaluation allows several methods to support shortcut fusion.
-   * Shortcut fusion is an optimization to merge iteratee calls; this avoids
-   * the creation of intermediate arrays and can greatly reduce the number of
-   * iteratee executions. Sections of a chain sequence qualify for shortcut
-   * fusion if the section is applied to an array of at least `200` elements
-   * and any iteratees accept only one argument. The heuristic for whether a
-   * section qualifies for shortcut fusion is subject to change.
+   * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
+   * fusion is an optimization to merge iteratee calls; this avoids the creation
+   * of intermediate arrays and can greatly reduce the number of iteratee executions.
+   * Sections of a chain sequence qualify for shortcut fusion if the section is
+   * applied to an array of at least two hundred elements and any iteratees
+   * accept only one argument. The heuristic for whether a section qualifies
+   * for shortcut fusion is subject to change.
    *
    * Chaining is supported in custom builds as long as the `_#value` method is
    * directly or indirectly included in the build.
    * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
    * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
    * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
-   * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
-   * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
-   * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
-   * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
-   * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
-   * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
-   * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
-   * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
-   * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
-   * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
-   * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
-   * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
-   * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
-   * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
-   * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
-   * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
-   * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
-   * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
-   * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
-   * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
-   * `zipObject`, `zipObjectDeep`, and `zipWith`
+   * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`,
+   * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`,
+   * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flattenDepth`,
+   * `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, `functionsIn`,
+   * `groupBy`, `initial`, `intersection`, `intersectionBy`, `intersectionWith`,
+   * `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, `keys`, `keysIn`,
+   * `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, `memoize`,
+   * `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, `nthArg`,
+   * `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, `overEvery`,
+   * `overSome`, `partial`, `partialRight`, `partition`, `pick`, `pickBy`, `plant`,
+   * `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, `pullAt`, `push`,
+   * `range`, `rangeRight`, `rearg`, `reject`, `remove`, `rest`, `reverse`,
+   * `sampleSize`, `set`, `setWith`, `shuffle`, `slice`, `sort`, `sortBy`,
+   * `splice`, `spread`, `tail`, `take`, `takeRight`, `takeRightWhile`,
+   * `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, `toPairs`, `toPairsIn`,
+   * `toPath`, `toPlainObject`, `transform`, `unary`, `union`, `unionBy`,
+   * `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, `unshift`, `unzip`,
+   * `unzipWith`, `values`, `valuesIn`, `without`, `wrap`, `xor`, `xorBy`,
+   * `xorWith`, `zip`, `zipObject`, `zipObjectDeep`, and `zipWith`
    *
    * The wrapper methods that are **not** chainable by default are:
    * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
-   * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `divide`, `each`,
-   * `eachRight`, `endsWith`, `eq`, `escape`, `escapeRegExp`, `every`, `find`,
-   * `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `first`,
-   * `floor`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`,
-   * `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`, `head`, `identity`,
-   * `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`, `isArray`,
-   * `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`, `isBuffer`,
-   * `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`, `isError`,
-   * `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`, `isMatch`,
-   * `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
+   * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `endsWith`, `eq`,
+   * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
+   * `findLastIndex`, `findLastKey`, `floor`, `forEach`, `forEachRight`, `forIn`,
+   * `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`,
+   * `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`,
+   * `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`,
+   * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`,
+   * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`,
+   * `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
    * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`,
    * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`,
    * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`,
-   * `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, `min`, `minBy`, `multiply`,
-   * `noConflict`, `noop`, `now`, `nth`, `pad`, `padEnd`, `padStart`, `parseInt`,
-   * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `round`,
-   * `runInContext`, `sample`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`,
-   * `sortedIndexBy`, `sortedLastIndex`, `sortedLastIndexBy`, `startCase`,
-   * `startsWith`, `subtract`, `sum`, `sumBy`, `template`, `times`, `toInteger`,
-   * `toJSON`, `toLength`, `toLower`, `toNumber`, `toSafeInteger`, `toString`,
-   * `toUpper`, `trim`, `trimEnd`, `trimStart`, `truncate`, `unescape`,
-   * `uniqueId`, `upperCase`, `upperFirst`, `value`, and `words`
+   * `lt`, `lte`, `max`, `maxBy`, `mean`, `min`, `minBy`, `noConflict`, `noop`,
+   * `now`, `pad`, `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`,
+   * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `sample`,
+   * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`,
+   * `sortedLastIndex`, `sortedLastIndexBy`, `startCase`, `startsWith`, `subtract`,
+   * `sum`, `sumBy`, `template`, `times`, `toLower`, `toInteger`, `toLength`,
+   * `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, `trimEnd`,
+   * `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, `upperFirst`,
+   * `value`, and `words`
    *
    * @name _
    * @constructor
    * // => true
    */
   function lodash(value) {
-    return value instanceof LodashWrapper
-      ? value
-      : new LodashWrapper(value);
+    if (isObjectLike(value) && !isArray(value)) {
+      if (value instanceof LodashWrapper) {
+        return value;
+      }
+      if (hasOwnProperty.call(value, '__wrapped__')) {
+        return wrapperClone(value);
+      }
+    }
+    return new LodashWrapper(value);
   }
 
   /**
    *
    * @private
    * @param {*} value The value to wrap.
-   * @param {boolean} [chainAll] Enable explicit method chain sequences.
+   * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
    */
   function LodashWrapper(value, chainAll) {
     this.__wrapped__ = value;
     this.__chain__ = !!chainAll;
   }
 
-  LodashWrapper.prototype = baseCreate(lodash.prototype);
-  LodashWrapper.prototype.constructor = LodashWrapper;
-
   /*------------------------------------------------------------------------*/
 
   /**
   }
 
   /**
+   * Casts `value` to `identity` if it's not a function.
+   *
+   * @private
+   * @param {*} value The value to inspect.
+   * @returns {Array} Returns the array-like object.
+   */
+  function baseCastFunction(value) {
+    return typeof value == 'function' ? value : identity;
+  }
+
+  /**
    * The base implementation of `_.create` without support for assigning
    * properties to the created object.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} predicate The function invoked per iteration.
-   * @returns {boolean} Returns `true` if all elements pass the predicate check,
-   *  else `false`
+   * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`
    */
   function baseEvery(collection, predicate) {
     var result = true;
   }
 
   /**
-   * The base implementation of methods like `_.max` and `_.min` which accepts a
-   * `comparator` to determine the extremum value.
-   *
-   * @private
-   * @param {Array} array The array to iterate over.
-   * @param {Function} iteratee The iteratee invoked per iteration.
-   * @param {Function} comparator The comparator used to compare values.
-   * @returns {*} Returns the extremum value.
-   */
-  function baseExtremum(array, iteratee, comparator) {
-    var index = -1,
-        length = array.length;
-
-    while (++index < length) {
-      var value = array[index],
-          current = iteratee(value);
-
-      if (current != null && (computed === undefined
-            ? (current === current && !false)
-            : comparator(current, computed)
-          )) {
-        var computed = current,
-            result = value;
-      }
-    }
-    return result;
-  }
-
-  /**
    * The base implementation of `_.filter` without support for iteratee shorthands.
    *
    * @private
    * @private
    * @param {Array} array The array to flatten.
    * @param {number} depth The maximum recursion depth.
-   * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
-   * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
+   * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
    * @param {Array} [result=[]] The initial result value.
    * @returns {Array} Returns the new flattened array.
    */
-  function baseFlatten(array, depth, predicate, isStrict, result) {
+  function baseFlatten(array, depth, isStrict, result) {
+    result || (result = []);
+
     var index = -1,
         length = array.length;
 
-    predicate || (predicate = isFlattenable);
-    result || (result = []);
-
     while (++index < length) {
       var value = array[index];
-      if (depth > 0 && predicate(value)) {
+      if (depth > 0 && isArrayLikeObject(value) &&
+          (isStrict || isArray(value) || isArguments(value))) {
         if (depth > 1) {
           // Recursively flatten arrays (susceptible to call stack limits).
-          baseFlatten(value, depth - 1, predicate, isStrict, result);
+          baseFlatten(value, depth - 1, isStrict, result);
         } else {
           arrayPush(result, value);
         }
   }
 
   /**
-   * The base implementation of `baseForOwn` which iterates over `object`
-   * properties returned by `keysFunc` and invokes `iteratee` for each property.
-   * Iteratee functions may exit iteration early by explicitly returning `false`.
+   * The base implementation of `baseForIn` and `baseForOwn` which iterates
+   * over `object` properties returned by `keysFunc` invoking `iteratee` for
+   * each property. Iteratee functions may exit iteration early by explicitly
+   * returning `false`.
    *
    * @private
    * @param {Object} object The object to iterate over.
   }
 
   /**
-   * The base implementation of `_.gt` which doesn't coerce arguments to numbers.
-   *
-   * @private
-   * @param {*} value The value to compare.
-   * @param {*} other The other value to compare.
-   * @returns {boolean} Returns `true` if `value` is greater than `other`,
-   *  else `false`.
-   */
-  function baseGt(value, other) {
-    return value > other;
-  }
-
-  /**
    * The base implementation of `_.isEqual` which supports partial comparisons
    * and tracks traversed objects.
    *
    * @param {Object} other The other object to compare.
    * @param {Function} equalFunc The function to determine equivalents of values.
    * @param {Function} [customizer] The function to customize comparisons.
-   * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
-   *  for more details.
+   * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
    * @param {Object} [stack] Tracks traversed `object` and `other` objects.
    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
    */
 
     if (!objIsArr) {
       objTag = objectToString.call(object);
-      objTag = objTag == argsTag ? objectTag : objTag;
+      if (objTag == argsTag) {
+        objTag = objectTag;
+      }
     }
     if (!othIsArr) {
       othTag = objectToString.call(other);
-      othTag = othTag == argsTag ? objectTag : othTag;
+      if (othTag == argsTag) {
+        othTag = objectTag;
+      }
     }
     var objIsObj = objTag == objectTag && !isHostObject(object),
         othIsObj = othTag == objectTag && !isHostObject(other),
         isSameTag = objTag == othTag;
 
-    stack || (stack = []);
-    var stacked = find(stack, function(entry) {
-      return entry[0] === object;
-    });
-    if (stacked && stacked[1]) {
-      return stacked[1] == other;
-    }
-    stack.push([object, other]);
-    if (isSameTag && !objIsObj) {
-      var result = (objIsArr || isTypedArray(object))
-        ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
-        : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
-      stack.pop();
-      return result;
+    if (isSameTag && !(objIsArr || objIsObj)) {
+      return equalByTag(object, other, objTag, equalFunc, customizer, bitmask);
     }
-    if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
+    var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
+    if (!isPartial) {
       var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
           othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
 
       if (objIsWrapped || othIsWrapped) {
-        var objUnwrapped = objIsWrapped ? object.value() : object,
-            othUnwrapped = othIsWrapped ? other.value() : other;
-
-        var result = equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
-        stack.pop();
-        return result;
+        return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, bitmask, stack);
       }
     }
     if (!isSameTag) {
       return false;
     }
-    var result = equalObjects(object, other, equalFunc, customizer, bitmask, stack);
+    stack || (stack = []);
+    var stacked = find(stack, function(entry) {
+      return entry[0] === object;
+    });
+    if (stacked && stacked[1]) {
+      return stacked[1] == other;
+    }
+    stack.push([object, other]);
+    var result =  (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack);
     stack.pop();
     return result;
   }
    * @returns {Function} Returns the iteratee.
    */
   function baseIteratee(func) {
-    if (typeof func == 'function') {
+    var type = typeof func;
+    if (type == 'function') {
       return func;
     }
-    if (func == null) {
-      return identity;
-    }
-    return (typeof func == 'object' ? baseMatches : baseProperty)(func);
+    return func == null
+      ? identity
+      : (type == 'object' ? baseMatches : baseProperty)(func);
   }
 
   /**
   }
 
   /**
-   * The base implementation of `_.lt` which doesn't coerce arguments to numbers.
-   *
-   * @private
-   * @param {*} value The value to compare.
-   * @param {*} other The other value to compare.
-   * @returns {boolean} Returns `true` if `value` is less than `other`,
-   *  else `false`.
-   */
-  function baseLt(value, other) {
-    return value < other;
-  }
-
-  /**
    * The base implementation of `_.map` without support for iteratee shorthands.
    *
    * @private
 
   /**
    * The base implementation of `_.pick` without support for individual
-   * property identifiers.
+   * property names.
    *
    * @private
    * @param {Object} object The source object.
-   * @param {string[]} props The property identifiers to pick.
+   * @param {string[]} props The property names to pick.
    * @returns {Object} Returns the new object.
    */
   function basePick(object, props) {
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} predicate The function invoked per iteration.
-   * @returns {boolean} Returns `true` if any element passes the predicate check,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
    */
   function baseSome(collection, predicate) {
     var result;
   }
 
   /**
-   * Compares values to sort them in ascending order.
+   * Copies properties of `source` to `object`.
    *
    * @private
-   * @param {*} value The value to compare.
-   * @param {*} other The other value to compare.
-   * @returns {number} Returns the sort order indicator for `value`.
+   * @param {Object} source The object to copy properties from.
+   * @param {Array} props The property names to copy.
+   * @param {Object} [object={}] The object to copy properties to.
+   * @returns {Object} Returns `object`.
    */
-  function compareAscending(value, other) {
-    if (value !== other) {
-      var valIsDefined = value !== undefined,
-          valIsNull = value === null,
-          valIsReflexive = value === value,
-          valIsSymbol = false;
-
-      var othIsDefined = other !== undefined,
-          othIsNull = other === null,
-          othIsReflexive = other === other,
-          othIsSymbol = false;
-
-      if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
-          (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
-          (valIsNull && othIsDefined && othIsReflexive) ||
-          (!valIsDefined && othIsReflexive) ||
-          !valIsReflexive) {
-        return 1;
-      }
-      if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
-          (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
-          (othIsNull && valIsDefined && valIsReflexive) ||
-          (!othIsDefined && valIsReflexive) ||
-          !othIsReflexive) {
-        return -1;
-      }
-    }
-    return 0;
-  }
+  var copyObject = copyObjectWith;
 
   /**
-   * Copies properties of `source` to `object`.
+   * This function is like `copyObject` except that it accepts a function to
+   * customize copied values.
    *
    * @private
    * @param {Object} source The object to copy properties from.
-   * @param {Array} props The property identifiers to copy.
+   * @param {Array} props The property names to copy.
    * @param {Object} [object={}] The object to copy properties to.
    * @param {Function} [customizer] The function to customize copied values.
    * @returns {Object} Returns `object`.
    */
-  function copyObject(source, props, object, customizer) {
+  function copyObjectWith(source, props, object, customizer) {
     object || (object = {});
 
     var index = -1,
   }
 
   /**
-   * Creates a base function for methods like `_.forIn` and `_.forOwn`.
+   * Creates a base function for methods like `_.forIn`.
    *
    * @private
    * @param {boolean} [fromRight] Specify iterating from right to left.
    */
   function createCtorWrapper(Ctor) {
     return function() {
-      // Use a `switch` statement to work with class constructors. See
-      // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
+      // Use a `switch` statement to work with class constructors.
+      // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
       // for more details.
       var args = arguments;
       var thisBinding = baseCreate(Ctor.prototype),
   }
 
   /**
-   * Creates a function that wraps `func` to invoke it with the `this` binding
-   * of `thisArg` and `partials` prepended to the arguments it receives.
+   * Creates a function that wraps `func` to invoke it with the optional `this`
+   * binding of `thisArg` and the `partials` prepended to those provided to
+   * the wrapper.
    *
    * @private
    * @param {Function} func The function to wrap.
-   * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
-   *  for more details.
+   * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
    * @param {*} thisArg The `this` binding of `func`.
-   * @param {Array} partials The arguments to prepend to those provided to
-   *  the new function.
+   * @param {Array} partials The arguments to prepend to those provided to the new function.
    * @returns {Function} Returns the new wrapped function.
    */
   function createPartialWrapper(func, bitmask, thisArg, partials) {
    * @param {Array} array The array to compare.
    * @param {Array} other The other array to compare.
    * @param {Function} equalFunc The function to determine equivalents of values.
-   * @param {Function} customizer The function to customize comparisons.
-   * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
-   *  for more details.
-   * @param {Object} stack Tracks traversed `array` and `other` objects.
+   * @param {Function} [customizer] The function to customize comparisons.
+   * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
+   * @param {Object} [stack] Tracks traversed `array` and `other` objects.
    * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
    */
   function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
       // Recursively compare arrays (susceptible to call stack limits).
       if (isUnordered) {
         if (!baseSome(other, function(othValue) {
-              return arrValue === othValue ||
-                equalFunc(arrValue, othValue, customizer, bitmask, stack);
+              return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack);
             })) {
           result = false;
           break;
         }
-      } else if (!(
-            arrValue === othValue ||
-              equalFunc(arrValue, othValue, customizer, bitmask, stack)
-          )) {
+      } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
         result = false;
         break;
       }
    * @param {Object} other The other object to compare.
    * @param {string} tag The `toStringTag` of the objects to compare.
    * @param {Function} equalFunc The function to determine equivalents of values.
-   * @param {Function} customizer The function to customize comparisons.
-   * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
-   *  for more details.
-   * @param {Object} stack Tracks traversed `object` and `other` objects.
+   * @param {Function} [customizer] The function to customize comparisons.
+   * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
    */
-  function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
+  function equalByTag(object, other, tag, equalFunc, customizer, bitmask) {
     switch (tag) {
 
       case boolTag:
       case dateTag:
-        // Coerce dates and booleans to numbers, dates to milliseconds and
-        // booleans to `1` or `0` treating invalid dates coerced to `NaN` as
-        // not equal.
+        // Coerce dates and booleans to numbers, dates to milliseconds and booleans
+        // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
         return +object == +other;
 
       case errorTag:
 
       case regexpTag:
       case stringTag:
-        // Coerce regexes to strings and treat strings, primitives and objects,
-        // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring
-        // for more details.
+        // Coerce regexes to strings and treat strings primitives and string
+        // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
         return object == (other + '');
 
     }
    * @param {Object} object The object to compare.
    * @param {Object} other The other object to compare.
    * @param {Function} equalFunc The function to determine equivalents of values.
-   * @param {Function} customizer The function to customize comparisons.
-   * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
-   *  for more details.
-   * @param {Object} stack Tracks traversed `object` and `other` objects.
+   * @param {Function} [customizer] The function to customize comparisons.
+   * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
+   * @param {Object} [stack] Tracks traversed `object` and `other` objects.
    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
    */
   function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
   /**
    * Gets the "length" property value of `object`.
    *
-   * **Note:** This function is used to avoid a
-   * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects
-   * Safari on at least iOS 8.1-8.3 ARM64.
+   * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
+   * that affects Safari on at least iOS 8.1-8.3 ARM64.
    *
    * @private
    * @param {Object} object The object to query.
   }
 
   /**
-   * Checks if `value` is a flattenable `arguments` object or array.
-   *
-   * @private
-   * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
-   */
-  function isFlattenable(value) {
-    return isArrayLikeObject(value) && (isArray(value) || isArguments(value));
-  }
-
-  /**
-   * Checks if `value` is a valid array-like index.
-   *
-   * @private
-   * @param {*} value The value to check.
-   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
-   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
-   */
-  function isIndex(value, length) {
-    length = length == null ? MAX_SAFE_INTEGER : length;
-    return !!length &&
-      (typeof value == 'number' || reIsUint.test(value)) &&
-      (value > -1 && value % 1 == 0 && value < length);
-  }
-
-  /**
    * Checks if `value` is likely a prototype object.
    *
    * @private
    */
   function isPrototype(value) {
     var Ctor = value && value.constructor,
-        proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+        proto = (isFunction(Ctor) && Ctor.prototype) || objectProto;
 
     return value === proto;
   }
 
   /**
-   * Converts `value` to a string key if it's not a string or symbol.
+   * Creates a clone of `wrapper`.
    *
    * @private
-   * @param {*} value The value to inspect.
-   * @returns {string|symbol} Returns the key.
+   * @param {Object} wrapper The wrapper to clone.
+   * @returns {Object} Returns the cloned wrapper.
    */
-  var toKey = String;
+  function wrapperClone(wrapper) {
+    var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
+    result.__actions__ = copyArray(wrapper.__actions__);
+    return result;
+  }
 
   /*------------------------------------------------------------------------*/
 
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Array
    * @param {Array} array The array to compact.
    * @returns {Array} Returns the new array of filtered values.
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Array
    * @param {Array} array The array to concatenate.
    * @param {...*} [values] The values to concatenate.
    * console.log(array);
    * // => [1]
    */
-  function concat() {
-    var length = arguments.length,
-        array = castArray(arguments[0]);
-
-    if (length < 2) {
-      return length ? copyArray(array) : [];
-    }
-    var args = Array(length - 1);
-    while (length--) {
-      args[length - 1] = arguments[length];
+  var concat = rest(function(array, values) {
+    if (!isArray(array)) {
+      array = array == null ? [] : [Object(array)];
     }
-    return arrayConcat(array, baseFlatten(args, 1));
-  }
+    values = baseFlatten(values, 1);
+    return arrayConcat(array, values);
+  });
 
   /**
    * Flattens `array` a single level deep.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Array
    * @param {Array} array The array to flatten.
    * @returns {Array} Returns the new flattened array.
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Array
    * @param {Array} array The array to flatten.
    * @returns {Array} Returns the new flattened array.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @alias first
    * @category Array
    * @param {Array} array The array to query.
    * // => undefined
    */
   function head(array) {
-    return (array && array.length) ? array[0] : undefined;
+    return array ? array[0] : undefined;
   }
 
   /**
    * Gets the index at which the first occurrence of `value` is found in `array`
    * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
-   * for equality comparisons. If `fromIndex` is negative, it's used as the
-   * offset from the end of `array`.
+   * for equality comparisons. If `fromIndex` is negative, it's used as the offset
+   * from the end of `array`.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Array
    * @param {Array} array The array to search.
    * @param {*} value The value to search for.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Array
    * @param {Array} array The array to query.
    * @returns {*} Returns the last element of `array`.
   /**
    * Creates a slice of `array` from `start` up to, but not including, `end`.
    *
-   * **Note:** This method is used instead of
-   * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
-   * returned.
+   * **Note:** This method is used instead of [`Array#slice`](https://mdn.io/Array/slice)
+   * to ensure dense arrays are returned.
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Array
    * @param {Array} array The array to slice.
    * @param {number} [start=0] The start position.
   /*------------------------------------------------------------------------*/
 
   /**
-   * Creates a `lodash` wrapper instance that wraps `value` with explicit method
-   * chain sequences enabled. The result of such sequences must be unwrapped
-   * with `_#value`.
+   * Creates a `lodash` object that wraps `value` with explicit method chaining enabled.
+   * The result of such method chaining must be unwrapped with `_#value`.
    *
    * @static
    * @memberOf _
-   * @since 1.3.0
    * @category Seq
    * @param {*} value The value to wrap.
    * @returns {Object} Returns the new `lodash` wrapper instance.
   /**
    * This method invokes `interceptor` and returns `value`. The interceptor
    * is invoked with one argument; (value). The purpose of this method is to
-   * "tap into" a method chain sequence in order to modify intermediate results.
+   * "tap into" a method chain in order to modify intermediate results.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Seq
    * @param {*} value The value to provide to `interceptor`.
    * @param {Function} interceptor The function to invoke.
   /**
    * This method is like `_.tap` except that it returns the result of `interceptor`.
    * The purpose of this method is to "pass thru" values replacing intermediate
-   * results in a method chain sequence.
+   * results in a method chain.
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Seq
    * @param {*} value The value to provide to `interceptor`.
    * @param {Function} interceptor The function to invoke.
   }
 
   /**
-   * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
+   * Enables explicit method chaining on the wrapper object.
    *
    * @name chain
    * @memberOf _
-   * @since 0.1.0
    * @category Seq
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
   }
 
   /**
-   * Executes the chain sequence to resolve the unwrapped value.
+   * Executes the chained sequence to extract the unwrapped value.
    *
    * @name value
    * @memberOf _
-   * @since 0.1.0
    * @alias toJSON, valueOf
    * @category Seq
    * @returns {*} Returns the resolved unwrapped value.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
-   * @param {Array|Function|Object|string} [predicate=_.identity]
-   *  The function invoked per iteration.
-   * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
-   * @returns {boolean} Returns `true` if all elements pass the predicate check,
-   *  else `false`.
+   * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+   * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+   * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`.
    * @example
    *
    * _.every([true, 1, null, 'yes'], Boolean);
    * // => false
    *
    * var users = [
-   *   { 'user': 'barney', 'age': 36, 'active': false },
-   *   { 'user': 'fred',   'age': 40, 'active': false }
+   *   { 'user': 'barney', 'active': false },
+   *   { 'user': 'fred',   'active': false }
    * ];
    *
    * // The `_.matches` iteratee shorthand.
 
   /**
    * Iterates over elements of `collection`, returning an array of all elements
-   * `predicate` returns truthy for. The predicate is invoked with three
-   * arguments: (value, index|key, collection).
+   * `predicate` returns truthy for. The predicate is invoked with three arguments:
+   * (value, index|key, collection).
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
-   * @param {Array|Function|Object|string} [predicate=_.identity]
-   *  The function invoked per iteration.
+   * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new filtered array.
-   * @see _.reject
    * @example
    *
    * var users = [
 
   /**
    * Iterates over elements of `collection`, returning the first element
-   * `predicate` returns truthy for. The predicate is invoked with three
-   * arguments: (value, index|key, collection).
+   * `predicate` returns truthy for. The predicate is invoked with three arguments:
+   * (value, index|key, collection).
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to search.
-   * @param {Array|Function|Object|string} [predicate=_.identity]
-   *  The function invoked per iteration.
+   * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
    * @returns {*} Returns the matched element, else `undefined`.
    * @example
    *
   }
 
   /**
-   * Iterates over elements of `collection` and invokes `iteratee` for each element.
+   * Iterates over elements of `collection` invoking `iteratee` for each element.
    * The iteratee is invoked with three arguments: (value, index|key, collection).
    * Iteratee functions may exit iteration early by explicitly returning `false`.
    *
-   * **Note:** As with other "Collections" methods, objects with a "length"
-   * property are iterated like arrays. To avoid this behavior use `_.forIn`
-   * or `_.forOwn` for object iteration.
+   * **Note:** As with other "Collections" methods, objects with a "length" property
+   * are iterated like arrays. To avoid this behavior use `_.forIn` or `_.forOwn`
+   * for object iteration.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @alias each
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array|Object} Returns `collection`.
-   * @see _.forEachRight
    * @example
    *
    * _([1, 2]).forEach(function(value) {
    *   console.log(value);
    * });
-   * // => Logs `1` then `2`.
+   * // => logs `1` then `2`
    *
    * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
    *   console.log(key);
    * });
-   * // => Logs 'a' then 'b' (iteration order is not guaranteed).
+   * // => logs 'a' then 'b' (iteration order is not guaranteed)
    */
   function forEach(collection, iteratee) {
-    return baseEach(collection, baseIteratee(iteratee));
+    return baseEach(collection, baseCastFunction(iteratee));
   }
 
   /**
-   * Creates an array of values by running each element in `collection` thru
+   * Creates an array of values by running each element in `collection` through
    * `iteratee`. The iteratee is invoked with three arguments:
    * (value, index|key, collection).
    *
    * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
    *
    * The guarded methods are:
-   * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
-   * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
-   * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
-   * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
+   * `ary`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, `fill`,
+   * `invert`, `parseInt`, `random`, `range`, `rangeRight`, `slice`, `some`,
+   * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimEnd`, `trimStart`,
+   * and `words`
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
-   * @param {Array|Function|Object|string} [iteratee=_.identity]
-   *  The function invoked per iteration.
+   * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new mapped array.
    * @example
    *
 
   /**
    * Reduces `collection` to a value which is the accumulated result of running
-   * each element in `collection` thru `iteratee`, where each successive
+   * each element in `collection` through `iteratee`, where each successive
    * invocation is supplied the return value of the previous. If `accumulator`
-   * is not given, the first element of `collection` is used as the initial
+   * is not given the first element of `collection` is used as the initial
    * value. The iteratee is invoked with four arguments:
    * (accumulator, value, index|key, collection).
    *
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @param {*} [accumulator] The initial value.
    * @returns {*} Returns the accumulated value.
-   * @see _.reduceRight
    * @example
    *
    * _.reduce([1, 2], function(sum, n) {
 
   /**
    * Gets the size of `collection` by returning its length for array-like
-   * values or the number of own enumerable string keyed properties for objects.
+   * values or the number of own enumerable properties for objects.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to inspect.
    * @returns {number} Returns the collection size.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
-   * @param {Array|Function|Object|string} [predicate=_.identity]
-   *  The function invoked per iteration.
-   * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
-   * @returns {boolean} Returns `true` if any element passes the predicate check,
-   *  else `false`.
+   * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+   * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+   * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
    * @example
    *
    * _.some([null, 0, 'yes', false], Boolean);
 
   /**
    * Creates an array of elements, sorted in ascending order by the results of
-   * running each element in a collection thru each iteratee. This method
+   * running each element in a collection through each iteratee. This method
    * performs a stable sort, that is, it preserves the original sort order of
    * equal elements. The iteratees are invoked with one argument: (value).
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
-   * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])}
-   *  [iteratees=[_.identity]] The iteratees to sort by.
+   * @param {...(Function|Function[]|Object|Object[]|string|string[])} [iteratees=[_.identity]]
+   *  The iteratees to sort by, specified individually or in arrays.
    * @returns {Array} Returns the new sorted array.
    * @example
    *
    * var users = [
    *   { 'user': 'fred',   'age': 48 },
    *   { 'user': 'barney', 'age': 36 },
-   *   { 'user': 'fred',   'age': 40 },
+   *   { 'user': 'fred',   'age': 42 },
    *   { 'user': 'barney', 'age': 34 }
    * ];
    *
    * _.sortBy(users, function(o) { return o.user; });
-   * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
+   * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
    *
    * _.sortBy(users, ['user', 'age']);
-   * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
+   * // => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
    *
    * _.sortBy(users, 'user', function(o) {
    *   return Math.floor(o.age / 10);
    * });
-   * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
+   * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
    */
   function sortBy(collection, iteratee) {
     var index = 0;
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Function
    * @param {number} n The number of calls at which `func` is no longer invoked.
    * @param {Function} func The function to restrict.
 
   /**
    * Creates a function that invokes `func` with the `this` binding of `thisArg`
-   * and `partials` prepended to the arguments it receives.
+   * and prepends any additional `_.bind` arguments to those provided to the
+   * bound function.
    *
    * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
    * may be used as a placeholder for partially applied arguments.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Function
    * @param {Function} func The function to bind.
    * @param {*} thisArg The `this` binding of `func`.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Function
    * @param {Function} func The function to defer.
    * @param {...*} [args] The arguments to invoke `func` with.
    * _.defer(function(text) {
    *   console.log(text);
    * }, 'deferred');
-   * // => Logs 'deferred' after one or more milliseconds.
+   * // => logs 'deferred' after one or more milliseconds
    */
   var defer = rest(function(func, args) {
     return baseDelay(func, 1, args);
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Function
    * @param {Function} func The function to delay.
    * @param {number} wait The number of milliseconds to delay invocation.
    * _.delay(function(text) {
    *   console.log(text);
    * }, 1000, 'later');
-   * // => Logs 'later' after one second.
+   * // => logs 'later' after one second
    */
   var delay = rest(function(func, wait, args) {
     return baseDelay(func, toNumber(wait) || 0, args);
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Function
    * @param {Function} predicate The predicate to negate.
    * @returns {Function} Returns the new function.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Function
    * @param {Function} func The function to restrict.
    * @returns {Function} Returns the new restricted function.
 
   /**
    * Creates a function that invokes `func` with the `this` binding of the
-   * created function and arguments from `start` and beyond provided as
-   * an array.
+   * created function and arguments from `start` and beyond provided as an array.
    *
-   * **Note:** This method is based on the
-   * [rest parameter](https://mdn.io/rest_parameters).
+   * **Note:** This method is based on the [rest parameter](https://mdn.io/rest_parameters).
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Function
    * @param {Function} func The function to apply a rest parameter to.
    * @param {number} [start=func.length-1] The start position of the rest parameter.
   /*------------------------------------------------------------------------*/
 
   /**
-   * Casts `value` as an array if it's not one.
-   *
-   * @static
-   * @memberOf _
-   * @since 4.4.0
-   * @category Lang
-   * @param {*} value The value to inspect.
-   * @returns {Array} Returns the cast array.
-   * @example
-   *
-   * _.castArray(1);
-   * // => [1]
-   *
-   * _.castArray({ 'a': 1 });
-   * // => [{ 'a': 1 }]
-   *
-   * _.castArray('abc');
-   * // => ['abc']
-   *
-   * _.castArray(null);
-   * // => [null]
-   *
-   * _.castArray(undefined);
-   * // => [undefined]
-   *
-   * _.castArray();
-   * // => []
-   *
-   * var array = [1, 2, 3];
-   * console.log(_.castArray(array) === array);
-   * // => true
-   */
-  function castArray() {
-    if (!arguments.length) {
-      return [];
-    }
-    var value = arguments[0];
-    return isArray(value) ? value : [value];
-  }
-
-  /**
    * Creates a shallow clone of `value`.
    *
    * **Note:** This method is loosely based on the
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to clone.
    * @returns {*} Returns the cloned value.
-   * @see _.cloneDeep
    * @example
    *
    * var objects = [{ 'a': 1 }, { 'b': 2 }];
   }
 
   /**
-   * Performs a
-   * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+   * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
    * comparison between two values to determine if they are equivalent.
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
   }
 
   /**
+   * Checks if `value` is greater than `other`.
+   *
+   * @static
+   * @memberOf _
+   * @category Lang
+   * @param {*} value The value to compare.
+   * @param {*} other The other value to compare.
+   * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`.
+   * @example
+   *
+   * _.gt(3, 1);
+   * // => true
+   *
+   * _.gt(3, 3);
+   * // => false
+   *
+   * _.gt(1, 3);
+   * // => false
+   */
+  function gt(value, other) {
+    return value > other;
+  }
+
+  /**
    * Checks if `value` is likely an `arguments` object.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isArguments(function() { return arguments; }());
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @type {Function}
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isArray([1, 2, 3]);
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
    * // => false
    */
   function isArrayLike(value) {
-    return value != null && isLength(getLength(value)) && !isFunction(value);
+    return value != null &&
+      !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value));
   }
 
   /**
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is an array-like object,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`.
    * @example
    *
    * _.isArrayLikeObject([1, 2, 3]);
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isBoolean(false);
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isDate(new Date);
   }
 
   /**
-   * Checks if `value` is an empty object, collection, map, or set.
-   *
-   * Objects are considered empty if they have no own enumerable string keyed
-   * properties.
-   *
-   * Array-like values such as `arguments` objects, arrays, buffers, strings, or
-   * jQuery-like collections are considered empty if they have a `length` of `0`.
-   * Similarly, maps and sets are considered empty if they have a `size` of `0`.
+   * Checks if `value` is empty. A value is considered empty unless it's an
+   * `arguments` object, array, string, or jQuery-like collection with a length
+   * greater than `0` or an object with own enumerable properties.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
-   * @param {*} value The value to check.
+   * @param {Array|Object|string} value The value to inspect.
    * @returns {boolean} Returns `true` if `value` is empty, else `false`.
    * @example
    *
           isFunction(value.splice) || isArguments(value))) {
       return !value.length;
     }
-    return !keys(value).length;
+    for (var key in value) {
+      if (hasOwnProperty.call(value, key)) {
+        return false;
+      }
+    }
+    return true;
   }
 
   /**
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
-   * @returns {boolean} Returns `true` if the values are equivalent,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
    * @example
    *
    * var object = { 'user': 'fred' };
   /**
    * Checks if `value` is a finite primitive number.
    *
-   * **Note:** This method is based on
-   * [`Number.isFinite`](https://mdn.io/Number/isFinite).
+   * **Note:** This method is based on [`Number.isFinite`](https://mdn.io/Number/isFinite).
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is a finite number,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
    * @example
    *
    * _.isFinite(3);
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isFunction(_);
    */
   function isFunction(value) {
     // The use of `Object#toString` avoids issues with the `typeof` operator
-    // in Safari 8 which returns 'object' for typed array and weak map constructors,
-    // and PhantomJS 1.9 which returns 'function' for `NodeList` instances.
+    // in Safari 8 which returns 'object' for typed array constructors, and
+    // PhantomJS 1.9 which returns 'function' for `NodeList` instances.
     var tag = isObject(value) ? objectToString.call(value) : '';
     return tag == funcTag || tag == genTag;
   }
   /**
    * Checks if `value` is a valid array-like length.
    *
-   * **Note:** This function is loosely based on
-   * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
+   * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is a valid length,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
    * @example
    *
    * _.isLength(3);
   }
 
   /**
-   * Checks if `value` is the
-   * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types)
-   * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an object, else `false`.
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   /**
    * Checks if `value` is `NaN`.
    *
-   * **Note:** This method is based on
-   * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
-   * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
-   * `undefined` and other non-number values.
+   * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
+   * which returns `true` for `undefined` and other non-numeric values.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
    */
   function isNaN(value) {
     // An `NaN` primitive is the only value that is not equal to itself.
-    // Perform the `toStringTag` check first to avoid errors with some
-    // ActiveX objects in IE.
+    // Perform the `toStringTag` check first to avoid errors with some ActiveX objects in IE.
     return isNumber(value) && value != +value;
   }
 
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
   /**
    * Checks if `value` is classified as a `Number` primitive or object.
    *
-   * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
-   * classified as numbers, use the `_.isFinite` method.
+   * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
+   * as numbers, use the `_.isFinite` method.
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isNumber(3);
    *
    * @static
    * @memberOf _
-   * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isRegExp(/abc/);
    * Checks if `value` is classified as a `String` primitive or object.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Lang
    * @param {*} value The value to check.
-   * @returns {boolean} Returns `true` if `value` is correctly classified,
-   *  else `false`.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
    * @example
    *
    * _.isString('abc');
    * Checks if `value` is `undefined`.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Lang
    * @param {*} value The value to check.
   }
 
   /**
+   * Checks if `value` is less than `other`.
+   *
+   * @static
+   * @memberOf _
+   * @category Lang
+   * @param {*} value The value to compare.
+   * @param {*} other The other value to compare.
+   * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.
+   * @example
+   *
+   * _.lt(1, 3);
+   * // => true
+   *
+   * _.lt(3, 3);
+   * // => false
+   *
+   * _.lt(3, 1);
+   * // => false
+   */
+  function lt(value, other) {
+    return value < other;
+  }
+
+  /**
    * Converts `value` to an array.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Lang
    * @param {*} value The value to convert.
   /**
    * Converts `value` to an integer.
    *
-   * **Note:** This function is loosely based on
-   * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger).
+   * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger).
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {number} Returns the converted integer.
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to process.
    * @returns {number} Returns the number.
   var toNumber = Number;
 
   /**
-   * Converts `value` to a string. An empty string is returned for `null`
-   * and `undefined` values. The sign of `-0` is preserved.
+   * Converts `value` to a string if it's not one. An empty string is returned
+   * for `null` and `undefined` values. The sign of `-0` is preserved.
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @category Lang
    * @param {*} value The value to process.
    * @returns {string} Returns the string.
   /*------------------------------------------------------------------------*/
 
   /**
-   * Assigns own enumerable string keyed properties of source objects to the
-   * destination object. Source objects are applied from left to right.
-   * Subsequent sources overwrite property assignments of previous sources.
+   * Assigns own enumerable properties of source objects to the destination
+   * object. Source objects are applied from left to right. Subsequent sources
+   * overwrite property assignments of previous sources.
    *
    * **Note:** This method mutates `object` and is loosely based on
    * [`Object.assign`](https://mdn.io/Object/assign).
    *
    * @static
    * @memberOf _
-   * @since 0.10.0
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
-   * @see _.assignIn
    * @example
    *
    * function Foo() {
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @alias extend
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
-   * @see _.assign
    * @example
    *
    * function Foo() {
   });
 
   /**
-   * This method is like `_.assignIn` except that it accepts `customizer`
-   * which is invoked to produce the assigned values. If `customizer` returns
-   * `undefined`, assignment is handled by the method instead. The `customizer`
-   * is invoked with five arguments: (objValue, srcValue, key, object, source).
+   * This method is like `_.assignIn` except that it accepts `customizer` which
+   * is invoked to produce the assigned values. If `customizer` returns `undefined`
+   * assignment is handled by the method instead. The `customizer` is invoked
+   * with five arguments: (objValue, srcValue, key, object, source).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
-   * @since 4.0.0
    * @alias extendWith
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} sources The source objects.
    * @param {Function} [customizer] The function to customize assigned values.
    * @returns {Object} Returns `object`.
-   * @see _.assignWith
    * @example
    *
    * function customizer(objValue, srcValue) {
    * // => { 'a': 1, 'b': 2 }
    */
   var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
-    copyObject(source, keysIn(source), object, customizer);
+    copyObjectWith(source, keysIn(source), object, customizer);
   });
 
   /**
-   * Creates an object that inherits from the `prototype` object. If a
-   * `properties` object is given, its own enumerable string keyed properties
-   * are assigned to the created object.
+   * Creates an object that inherits from the `prototype` object. If a `properties`
+   * object is given its own enumerable properties are assigned to the created object.
    *
    * @static
    * @memberOf _
-   * @since 2.3.0
    * @category Object
    * @param {Object} prototype The object to inherit from.
    * @param {Object} [properties] The properties to assign to the object.
   }
 
   /**
-   * Assigns own and inherited enumerable string keyed properties of source
-   * objects to the destination object for all destination properties that
-   * resolve to `undefined`. Source objects are applied from left to right.
-   * Once a property is set, additional values of the same property are ignored.
+   * Assigns own and inherited enumerable properties of source objects to the
+   * destination object for all destination properties that resolve to `undefined`.
+   * Source objects are applied from left to right. Once a property is set,
+   * additional values of the same property are ignored.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
-   * @see _.defaultsDeep
    * @example
    *
    * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
    * Checks if `path` is a direct property of `object`.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    * @returns {boolean} Returns `true` if `path` exists, else `false`.
    * @example
    *
-   * var object = { 'a': { 'b': 2 } };
-   * var other = _.create({ 'a': _.create({ 'b': 2 }) });
+   * var object = { 'a': { 'b': { 'c': 3 } } };
+   * var other = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) });
    *
    * _.has(object, 'a');
    * // => true
    *
-   * _.has(object, 'a.b');
+   * _.has(object, 'a.b.c');
    * // => true
    *
-   * _.has(object, ['a', 'b']);
+   * _.has(object, ['a', 'b', 'c']);
    * // => true
    *
    * _.has(other, 'a');
    * for more details.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names.
    * Creates an object composed of the picked `object` properties.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The source object.
-   * @param {...(string|string[])} [props] The property identifiers to pick.
+   * @param {...(string|string[])} [props] The property names to pick, specified
+   *  individually or in arrays.
    * @returns {Object} Returns the new object.
    * @example
    *
    * // => { 'a': 1, 'c': 3 }
    */
   var pick = rest(function(object, props) {
-    return object == null ? {} : basePick(object, baseMap(baseFlatten(props, 1), toKey));
+    return object == null ? {} : basePick(object, baseFlatten(props, 1));
   });
 
   /**
-   * This method is like `_.get` except that if the resolved value is a
-   * function it's invoked with the `this` binding of its parent object and
-   * its result is returned.
+   * This method is like `_.get` except that if the resolved value is a function
+   * it's invoked with the `this` binding of its parent object and its result
+   * is returned.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    * @param {Array|string} path The path of the property to resolve.
-   * @param {*} [defaultValue] The value returned for `undefined` resolved values.
+   * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
    * @returns {*} Returns the resolved value.
    * @example
    *
   }
 
   /**
-   * Creates an array of the own enumerable string keyed property values of `object`.
+   * Creates an array of the own enumerable property values of `object`.
    *
    * **Note:** Non-object values are coerced to objects.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    *
    * Though the ">" character is escaped for symmetry, characters like
    * ">" and "/" don't need escaping in HTML and have no special meaning
-   * unless they're part of a tag or unquoted attribute value. See
-   * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
+   * unless they're part of a tag or unquoted attribute value.
+   * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
    * (under "semi-related fun fact") for more details.
    *
    * Backticks are escaped because in IE < 9, they can break out of
    * attribute values or HTML comments. See [#59](https://html5sec.org/#59),
    * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
-   * [#133](https://html5sec.org/#133) of the
-   * [HTML5 Security Cheatsheet](https://html5sec.org/) for more details.
+   * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)
+   * for more details.
    *
-   * When working with HTML you should always
-   * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
-   * XSS vectors.
+   * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)
+   * to reduce XSS vectors.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category String
    * @param {string} [string=''] The string to escape.
    * This method returns the first argument given to it.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Util
    * @param {*} value Any value.
 
   /**
    * Creates a function that invokes `func` with the arguments of the created
-   * function. If `func` is a property name, the created function returns the
-   * property value for a given element. If `func` is an array or object, the
-   * created function returns `true` for elements that contain the equivalent
-   * source properties, otherwise it returns `false`.
+   * function. If `func` is a property name the created callback returns the
+   * property value for a given element. If `func` is an object the created
+   * callback returns `true` for elements that contain the equivalent object
+   * properties, otherwise it returns `false`.
    *
    * @static
-   * @since 4.0.0
    * @memberOf _
    * @category Util
    * @param {*} [func=_.identity] The value to convert to a callback.
    * @example
    *
    * var users = [
-   *   { 'user': 'barney', 'age': 36, 'active': true },
-   *   { 'user': 'fred',   'age': 40, 'active': false }
+   *   { 'user': 'barney', 'age': 36 },
+   *   { 'user': 'fred',   'age': 40 }
    * ];
    *
-   * // The `_.matches` iteratee shorthand.
-   * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
-   * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
-   *
-   * // The `_.matchesProperty` iteratee shorthand.
-   * _.filter(users, _.iteratee(['user', 'fred']));
-   * // => [{ 'user': 'fred', 'age': 40 }]
-   *
-   * // The `_.property` iteratee shorthand.
-   * _.map(users, _.iteratee('user'));
-   * // => ['barney', 'fred']
-   *
    * // Create custom iteratee shorthands.
-   * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
-   *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
-   *     return func.test(string);
+   * _.iteratee = _.wrap(_.iteratee, function(callback, func) {
+   *   var p = /^(\S+)\s*([<>])\s*(\S+)$/.exec(func);
+   *   return !p ? callback(func) : function(object) {
+   *     return (p[2] == '>' ? object[p[1]] > p[3] : object[p[1]] < p[3]);
    *   };
    * });
    *
-   * _.filter(['abc', 'def'], /ef/);
-   * // => ['def']
+   * _.filter(users, 'age > 36');
+   * // => [{ 'user': 'fred', 'age': 40 }]
    */
   var iteratee = baseIteratee;
 
    *
    * @static
    * @memberOf _
-   * @since 3.0.0
    * @category Util
    * @param {Object} source The object of property values to match.
    * @returns {Function} Returns the new function.
   }
 
   /**
-   * Adds all own enumerable string keyed function properties of a source
-   * object to the destination object. If `object` is a function, then methods
-   * are added to its prototype as well.
+   * Adds all own enumerable function properties of a source object to the
+   * destination object. If `object` is a function then methods are added to
+   * its prototype as well.
    *
    * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
    * avoid conflicts caused by modifying the original.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Util
    * @param {Function|Object} [object=lodash] The destination object.
    * @param {Object} source The object of functions to add.
-   * @param {Object} [options={}] The options object.
-   * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
+   * @param {Object} [options] The options object.
+   * @param {boolean} [options.chain=true] Specify whether the functions added
+   *  are chainable.
    * @returns {Function|Object} Returns `object`.
    * @example
    *
       object = this;
       methodNames = baseFunctions(source, keys(source));
     }
-    var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
+    var chain = (isObject(options) && 'chain' in options) ? options.chain : true,
         isFunc = isFunction(object);
 
     baseEach(methodNames, function(methodName) {
    * the `lodash` function.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Util
    * @returns {Function} Returns the `lodash` function.
    *
    * @static
    * @memberOf _
-   * @since 2.3.0
    * @category Util
    * @example
    *
   }
 
   /**
-   * Generates a unique ID. If `prefix` is given, the ID is appended to it.
+   * Generates a unique ID. If `prefix` is given the ID is appended to it.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Util
    * @param {string} [prefix=''] The value to prefix the ID with.
   /*------------------------------------------------------------------------*/
 
   /**
-   * Computes the maximum value of `array`. If `array` is empty or falsey,
+   * Computes the maximum value of `array`. If `array` is empty or falsey
    * `undefined` is returned.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Math
    * @param {Array} array The array to iterate over.
    */
   function max(array) {
     return (array && array.length)
-      ? baseExtremum(array, identity, baseGt)
+      ? baseExtremum(array, identity, gt)
       : undefined;
   }
 
   /**
-   * Computes the minimum value of `array`. If `array` is empty or falsey,
+   * Computes the minimum value of `array`. If `array` is empty or falsey
    * `undefined` is returned.
    *
    * @static
-   * @since 0.1.0
    * @memberOf _
    * @category Math
    * @param {Array} array The array to iterate over.
    */
   function min(array) {
     return (array && array.length)
-      ? baseExtremum(array, identity, baseLt)
+      ? baseExtremum(array, identity, lt)
       : undefined;
   }
 
   /*------------------------------------------------------------------------*/
 
-  // Add methods that return wrapped values in chain sequences.
+  LodashWrapper.prototype = baseCreate(lodash.prototype);
+  LodashWrapper.prototype.constructor = LodashWrapper;
+
+  // Add functions that return wrapped values when chaining.
   lodash.assignIn = assignIn;
   lodash.before = before;
   lodash.bind = bind;
   // Add aliases.
   lodash.extend = assignIn;
 
-  // Add methods to `lodash.prototype`.
+  // Add functions to `lodash.prototype`.
   mixin(lodash, lodash);
 
   /*------------------------------------------------------------------------*/
 
-  // Add methods that return unwrapped values in chain sequences.
+  // Add functions that return unwrapped values when chaining.
   lodash.clone = clone;
   lodash.escape = escape;
   lodash.every = every;
    */
   lodash.VERSION = VERSION;
 
-  // Add `Array` methods to `lodash.prototype`.
+  // Add `Array` and `String` methods to `lodash.prototype`.
   baseEach(['pop', 'join', 'replace', 'reverse', 'split', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
     var func = (/^(?:replace|split)$/.test(methodName) ? String.prototype : arrayProto)[methodName],
         chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
     lodash.prototype[methodName] = function() {
       var args = arguments;
       if (retUnwrapped && !this.__chain__) {
-        var value = this.value();
-        return func.apply(isArray(value) ? value : [], args);
+        return func.apply(this.value(), args);
       }
       return this[chainName](function(value) {
-        return func.apply(isArray(value) ? value : [], args);
+        return func.apply(value, args);
       });
     };
   });
 
-  // Add chain sequence methods to the `lodash` wrapper.
+  // Add chaining functions to the `lodash` wrapper.
   lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
 
   /*--------------------------------------------------------------------------*/
 
-  // Expose Lodash on the free variable `window` or `self` when available so it's
-  // globally accessible, even when bundled with Browserify, Webpack, etc. This
-  // also prevents errors in cases where Lodash is loaded by a script tag in the
-  // presence of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch
-  // for more details. Use `_.noConflict` to remove Lodash from the global object.
+  // Expose lodash on the free variable `window` or `self` when available. This
+  // prevents errors in cases where lodash is loaded by a script tag in the presence
+  // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details.
   (freeWindow || freeSelf || {})._ = lodash;
 
   // Some AMD build optimizers like r.js check for condition patterns like the following: