Add placeholder support to _.curry.

This commit is contained in:
John-David Dalton
2014-03-29 02:13:52 -07:00
parent bb42b87f4e
commit 141227d846
2 changed files with 58 additions and 36 deletions

View File

@@ -1275,14 +1275,19 @@
if (partialRightArgs) { if (partialRightArgs) {
args = composeArgsRight(partialRightArgs, partialRightHolders, args); args = composeArgsRight(partialRightArgs, partialRightHolders, args);
} }
if (isCurry && length < arity) { if (isCurry) {
bitmask |= PARTIAL_FLAG; var newPartialHolders = getHolders(args);
bitmask &= ~PARTIAL_RIGHT_FLAG length -= newPartialHolders.length;
if (!isCurryBound) {
bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); if (length < arity) {
bitmask |= PARTIAL_FLAG;
bitmask &= ~PARTIAL_RIGHT_FLAG
if (!isCurryBound) {
bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
}
var newArity = nativeMax(arity - length, 0);
return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, newPartialHolders]);
} }
var newArity = nativeMax(0, arity - length);
return baseCreateWrapper([func, bitmask, newArity, thisArg, args, null, []]);
} }
var thisBinding = isBind ? thisArg : this; var thisBinding = isBind ? thisArg : this;
if (isBindKey) { if (isBindKey) {
@@ -2051,11 +2056,9 @@
* provided to the new function. * provided to the new function.
* @param {Array} [partialRightArgs] An array of arguments to append to those * @param {Array} [partialRightArgs] An array of arguments to append to those
* provided to the new function. * provided to the new function.
* @param {Array} [partialHolders] An array of `partialArgs` placeholder indexes.
* @param {Array} [partialRightHolders] An array of `partialRightArgs` placeholder indexes.
* @returns {Function} Returns the new function. * @returns {Function} Returns the new function.
*/ */
function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders) { function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) {
var isBind = bitmask & BIND_FLAG, var isBind = bitmask & BIND_FLAG,
isBindKey = bitmask & BIND_KEY_FLAG, isBindKey = bitmask & BIND_KEY_FLAG,
isPartial = bitmask & PARTIAL_FLAG, isPartial = bitmask & PARTIAL_FLAG,
@@ -2118,17 +2121,17 @@
data[1] |= bitmask; data[1] |= bitmask;
return createWrapper.apply(null, data); return createWrapper.apply(null, data);
} }
if (arity == null) {
arity = isBindKey ? 0 : func.length;
} else if (arity < 0) {
arity = 0;
}
if (isPartial) { if (isPartial) {
partialHolders = getHolders(partialArgs); var partialHolders = getHolders(partialArgs);
} }
if (isPartialRight) { if (isPartialRight) {
partialRightHolders = getHolders(partialRightArgs); var partialRightHolders = getHolders(partialRightArgs);
} }
if (arity == null) {
arity = isBindKey ? 0 : func.length;
}
arity = nativeMax(arity, 0);
// fast path for `_.bind` // fast path for `_.bind`
data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders]; data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs, partialHolders, partialRightHolders];
return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG))

View File

@@ -1730,25 +1730,42 @@
(function() { (function() {
function fn(a, b, c, d) { function fn(a, b, c, d) {
return a + b + c + d; return slice.call(arguments);
} }
test('should curry based on the number of arguments provided', 3, function() { test('should curry based on the number of arguments provided', 3, function() {
var curried = _.curry(fn); var curried = _.curry(fn),
equal(curried(1)(2)(3)(4), 10); expected = [1, 2, 3, 4];
equal(curried(1, 2)(3, 4), 10);
equal(curried(1, 2, 3, 4), 10); deepEqual(curried(1)(2)(3)(4), expected);
deepEqual(curried(1, 2)(3, 4), expected);
deepEqual(curried(1, 2, 3, 4), expected);
}); });
test('should work with partialed methods', 2, function() { test('should work with partialed methods', 2, function() {
var curried = _.curry(fn), var curried = _.curry(fn),
a = _.partial(curried, 1), expected = [1, 2, 3, 4];
var a = _.partial(curried, 1),
b = _.bind(a, null, 2), b = _.bind(a, null, 2),
c = _.partialRight(b, 4), c = _.partialRight(b, 4),
d = _.partialRight(b(3), 4); d = _.partialRight(b(3), 4);
equal(c(3), 10); deepEqual(c(3), expected);
equal(d(), 10); deepEqual(d(), expected);
});
test('should support placeholders', 4, function() {
if (isPreBuild) {
var curried = _.curry(fn);
deepEqual(curried(1)(_, 3)(_, 4)(2), [1, 2, 3, 4]);
deepEqual(curried(_, 2)(1)(_, 4)(3), [1, 2, 3, 4]);
deepEqual(curried(_, _, 3)(_, 2)(_, 4)(1), [1, 2, 3, 4]);
deepEqual(curried(_, _, _, 4)(_, _, 3)(_, 2)(1), [1, 2, 3, 4]);
}
else {
skipTest(4);
}
}); });
test('should return a function with a `length` of `0`', 6, function() { test('should return a function with a `length` of `0`', 6, function() {
@@ -1774,22 +1791,24 @@
test('should not alter the `this` binding', 9, function() { test('should not alter the `this` binding', 9, function() {
var fn = function(a, b, c) { var fn = function(a, b, c) {
var value = this || {}; var value = this || {};
return value[a] + value[b] + value[c]; return [value[a], value[b], value[c]];
}; };
var object = { 'a': 1, 'b': 2, 'c': 3 }; var object = { 'a': 1, 'b': 2, 'c': 3 },
equal(_.curry(_.bind(fn, object), 3)('a')('b')('c'), 6); expected = [1, 2, 3];
equal(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), 6);
equal(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), 6);
ok(_.isEqual(_.bind(_.curry(fn), object)('a')('b')('c'), NaN)); deepEqual(_.curry(_.bind(fn, object), 3)('a')('b')('c'), expected);
ok(_.isEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), NaN)); deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b')('c'), expected);
equal(_.bind(_.curry(fn), object)('a', 'b', 'c'), 6); deepEqual(_.curry(_.bind(fn, object), 3)('a', 'b', 'c'), expected);
deepEqual(_.bind(_.curry(fn), object)('a')('b')('c'), Array(3));
deepEqual(_.bind(_.curry(fn), object)('a', 'b')('c'), Array(3));
deepEqual(_.bind(_.curry(fn), object)('a', 'b', 'c'), expected);
object.curried = _.curry(fn); object.curried = _.curry(fn);
ok(_.isEqual(object.curried('a')('b')('c'), NaN)); deepEqual(object.curried('a')('b')('c'), Array(3));
ok(_.isEqual(object.curried('a', 'b')('c'), NaN)); deepEqual(object.curried('a', 'b')('c'), Array(3));
equal(object.curried('a', 'b', 'c'), 6); deepEqual(object.curried('a', 'b', 'c'), expected);
}); });
}()); }());