Enable shortcut fusion for _.find and _.findLast.

This commit is contained in:
Graeme Yeates
2015-07-12 15:47:05 -04:00
committed by John-David Dalton
parent 1e344455b8
commit 39068730e2
2 changed files with 55 additions and 7 deletions

View File

@@ -842,8 +842,9 @@
*
* The wrapper methods that support shortcut fusion are:
* `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
* `first`, `initial`, `last`, `map`, `reject`, `rest`, `reverse`, `slice`,
* `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
* `find`, `findLast`, `first`, `initial`, `last`, `map`, `reject`, `rest`,
* `reverse`, `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`,
* and `toArray`
*
* The chainable wrapper methods are:
* `after`, `ary`, `assign`, `assignWith`, `at`, `before`, `bind`, `bindAll`,
@@ -11582,6 +11583,14 @@
return this.filter(identity);
};
LazyWrapper.prototype.find = function(predicate) {
return this.filter(predicate).first();
};
LazyWrapper.prototype.findLast = function(predicate) {
return this.reverse().find(predicate);
};
LazyWrapper.prototype.reject = function(predicate) {
predicate = getIteratee(predicate);
return this.filter(function(value) {
@@ -11619,14 +11628,15 @@
// Add `LazyWrapper` methods to `lodash.prototype`.
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),
retUnwrapped = /^(?:first|last)$/.test(methodName),
lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];
isTaker = /^(?:first|last)$/.test(methodName),
retUnwrapped = isTaker || /^find/.test(methodName),
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];
if (!lodashFunc) {
return;
}
lodash.prototype[methodName] = function() {
var args = retUnwrapped ? [1] : arguments,
var args = isTaker ? [1] : arguments,
chainAll = this.__chain__,
value = this.__wrapped__,
isHybrid = !!this.__actions__.length,
@@ -11640,7 +11650,7 @@
}
var interceptor = function(value) {
var result = lodashFunc.apply(lodash, arrayPush([value], args));
return (retUnwrapped && chainAll) ? result[0] : result;
return (isTaker && chainAll) ? result[0] : result;
};
var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined },
@@ -11653,7 +11663,7 @@
return func.apply(this, args);
}
var result = lodashFunc.apply(lodash, arrayPush([this.value()], args));
return result[0];
return isTaker ? result[0] : result;
}
if (!retUnwrapped && useLazy) {
value = onlyLazy ? value : new LazyWrapper(this);

View File

@@ -3977,6 +3977,44 @@
deepEqual(actual, expecting);
});
if (!/(Index|Key)/.test(methodName)) {
test('should enable shortcut fusion in chaining', 2, function() {
if (!isNpm) {
var callCount = 0;
var items = _.range(0, LARGE_ARRAY_SIZE + 1);
var expectedCalls = LARGE_ARRAY_SIZE / 2 + 1;
var expected = LARGE_ARRAY_SIZE / 2 - 25;
var result = _(items).map(function(x) {
callCount++;
return x - 25;
})[methodName](function(x) {
return x === expected;
});
strictEqual(callCount, expectedCalls);
strictEqual(result, expected);
} else {
skipTest(2);
}
});
test('should function when the only action in chaining', 2, function() {
if (!isNpm) {
var callCount = 0;
var items = _.range(0, LARGE_ARRAY_SIZE + 1);
var expectedCalls = LARGE_ARRAY_SIZE / 2 + 1;
var expected = LARGE_ARRAY_SIZE / 2;
var result = _(items)[methodName](function(x) {
callCount++;
return x === expected;
});
strictEqual(callCount, expectedCalls);
strictEqual(result, expected);
} else {
skipTest(2);
}
});
}
}());
(function() {