mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 19:07:49 +00:00
Add _.ary. [closes #814]
This commit is contained in:
71
lodash.js
71
lodash.js
@@ -22,7 +22,8 @@
|
|||||||
CURRY_BOUND_FLAG = 16,
|
CURRY_BOUND_FLAG = 16,
|
||||||
PARTIAL_FLAG = 32,
|
PARTIAL_FLAG = 32,
|
||||||
PARTIAL_RIGHT_FLAG = 64,
|
PARTIAL_RIGHT_FLAG = 64,
|
||||||
REARG_FLAG = 128;
|
ARY_FLAG = 128,
|
||||||
|
REARG_FLAG = 256;
|
||||||
|
|
||||||
/** Used as default options for `_.trunc`. */
|
/** Used as default options for `_.trunc`. */
|
||||||
var DEFAULT_TRUNC_LENGTH = 30,
|
var DEFAULT_TRUNC_LENGTH = 30,
|
||||||
@@ -2960,11 +2961,13 @@
|
|||||||
* @param {Array} [partialsRight] The arguments to append to those provided to the new function.
|
* @param {Array} [partialsRight] The arguments to append to those provided to the new function.
|
||||||
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
|
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
|
||||||
* @param {Array} [argPos] The argument positions of the new function.
|
* @param {Array} [argPos] The argument positions of the new function.
|
||||||
* @param {number} arity The arity of `func`.
|
* @param {number} [arity] The arity of `func`.
|
||||||
|
* @param {number} [ary] The arity cap of `func`.
|
||||||
* @returns {Function} Returns the new wrapped function.
|
* @returns {Function} Returns the new wrapped function.
|
||||||
*/
|
*/
|
||||||
function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, arity) {
|
function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, arity, ary) {
|
||||||
var isBind = bitmask & BIND_FLAG,
|
var isAry = bitmask & ARY_FLAG,
|
||||||
|
isBind = bitmask & BIND_FLAG,
|
||||||
isBindKey = bitmask & BIND_KEY_FLAG,
|
isBindKey = bitmask & BIND_KEY_FLAG,
|
||||||
isCurry = bitmask & CURRY_FLAG,
|
isCurry = bitmask & CURRY_FLAG,
|
||||||
isCurryRight = bitmask & CURRY_RIGHT_FLAG,
|
isCurryRight = bitmask & CURRY_RIGHT_FLAG,
|
||||||
@@ -2986,6 +2989,9 @@
|
|||||||
if (argPos) {
|
if (argPos) {
|
||||||
args = arrayReduceRight(argPos, reorder, args);
|
args = arrayReduceRight(argPos, reorder, args);
|
||||||
}
|
}
|
||||||
|
if (isAry && ary < length) {
|
||||||
|
args.length = ary;
|
||||||
|
}
|
||||||
if (partials) {
|
if (partials) {
|
||||||
args = composeArgs(args, partials, holders);
|
args = composeArgs(args, partials, holders);
|
||||||
}
|
}
|
||||||
@@ -3011,7 +3017,7 @@
|
|||||||
if (!isCurryBound) {
|
if (!isCurryBound) {
|
||||||
bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
|
bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
|
||||||
}
|
}
|
||||||
var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, newArity);
|
var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, newArity, ary);
|
||||||
result.placeholder = placeholder;
|
result.placeholder = placeholder;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -3099,15 +3105,17 @@
|
|||||||
* 16 - `_.curry` or `_.curryRight` of a bound function
|
* 16 - `_.curry` or `_.curryRight` of a bound function
|
||||||
* 32 - `_.partial`
|
* 32 - `_.partial`
|
||||||
* 64 - `_.partialRight`
|
* 64 - `_.partialRight`
|
||||||
* 128 - `_.rearg`
|
* 128 - `_.ary`
|
||||||
|
* 256 - `_.rearg`
|
||||||
* @param {*} [thisArg] The `this` binding of `func`.
|
* @param {*} [thisArg] The `this` binding of `func`.
|
||||||
* @param {Array} [partials] The arguments to be partially applied.
|
* @param {Array} [partials] The arguments to be partially applied.
|
||||||
* @param {Array} [holders] The `partials` placeholder indexes.
|
* @param {Array} [holders] The `partials` placeholder indexes.
|
||||||
* @param {Array} [argPos] The argument positions of the new function.
|
* @param {Array} [argPos] The argument positions of the new function.
|
||||||
* @param {number} [arity] The arity of `func`.
|
* @param {number} [arity] The arity of `func`.
|
||||||
|
* @param {number} [ary] The arity cap of `func`.
|
||||||
* @returns {Function} Returns the new wrapped function.
|
* @returns {Function} Returns the new wrapped function.
|
||||||
*/
|
*/
|
||||||
function createWrapper(func, bitmask, thisArg, partials, holders, argPos, arity) {
|
function createWrapper(func, bitmask, thisArg, partials, holders, argPos, arity, ary) {
|
||||||
var isBindKey = bitmask & BIND_KEY_FLAG;
|
var isBindKey = bitmask & BIND_KEY_FLAG;
|
||||||
if (!isBindKey && !isFunction(func)) {
|
if (!isBindKey && !isFunction(func)) {
|
||||||
throw new TypeError(FUNC_ERROR_TEXT);
|
throw new TypeError(FUNC_ERROR_TEXT);
|
||||||
@@ -3127,14 +3135,16 @@
|
|||||||
partials = holders = null;
|
partials = holders = null;
|
||||||
}
|
}
|
||||||
var data = !isBindKey && getData(func),
|
var data = !isBindKey && getData(func),
|
||||||
newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, arity];
|
newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, arity, ary];
|
||||||
|
|
||||||
if (data && data !== true && !(argPos && (data[3] || data[5]))) {
|
if (data && data !== true &&
|
||||||
|
!(bitmask > 127 && data[1] > 3) &&
|
||||||
|
!((bitmask > 3 && bitmask < 128) && data[1] > 127)) {
|
||||||
newData = mergeData(newData, data);
|
newData = mergeData(newData, data);
|
||||||
}
|
}
|
||||||
newData[8] = newData[8] == null
|
newData[8] = newData[8] == null
|
||||||
? (isBindKey ? 0 : newData[0].length)
|
? (isBindKey ? 0 : newData[0].length)
|
||||||
: nativeMax(newData[8] - length, 0) || 0;
|
: (nativeMax(newData[8] - length, 0) || 0);
|
||||||
|
|
||||||
bitmask = newData[1];
|
bitmask = newData[1];
|
||||||
if (bitmask == BIND_FLAG) {
|
if (bitmask == BIND_FLAG) {
|
||||||
@@ -3379,10 +3389,10 @@
|
|||||||
*/
|
*/
|
||||||
function mergeData(data, source) {
|
function mergeData(data, source) {
|
||||||
var bitmask = data[1],
|
var bitmask = data[1],
|
||||||
funcBitmask = source[1];
|
srcBitmask = source[1];
|
||||||
|
|
||||||
// Use metadata `thisArg` if available.
|
// Use source `thisArg` if available.
|
||||||
if (funcBitmask & BIND_FLAG) {
|
if (srcBitmask & BIND_FLAG) {
|
||||||
data[2] = source[2];
|
data[2] = source[2];
|
||||||
// Set when currying a bound function.
|
// Set when currying a bound function.
|
||||||
bitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
|
bitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
|
||||||
@@ -3408,13 +3418,17 @@
|
|||||||
push.apply(value, data[7]);
|
push.apply(value, data[7]);
|
||||||
data[7] = value;
|
data[7] = value;
|
||||||
}
|
}
|
||||||
// Use metadata `arity` if one is not provided.
|
// Use source `arity` if one is not provided.
|
||||||
if (data[8] == null) {
|
if (data[8] == null) {
|
||||||
data[8] = source[8];
|
data[8] = source[8];
|
||||||
}
|
}
|
||||||
// Use metadata `func` and merge bitmasks.
|
// Use source `ary` if it's smaller.
|
||||||
|
if (srcBitmask & ARY_FLAG) {
|
||||||
|
data[9] = data[9] == null ? source[9] : nativeMin(data[9], source[9]);
|
||||||
|
}
|
||||||
|
// Use source `func` and merge bitmasks.
|
||||||
data[0] = source[0];
|
data[0] = source[0];
|
||||||
data[1] = bitmask | funcBitmask;
|
data[1] = bitmask | srcBitmask;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -6273,6 +6287,30 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a function that accepts up to `n` arguments ignoring any
|
||||||
|
* additional arguments.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @category Function
|
||||||
|
* @param {Function} func The function to cap arguments for.
|
||||||
|
* @param {number} [n=func.length] The arity cap.
|
||||||
|
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||||||
|
* @returns {Function} Returns the new function.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* _.map(['6', '8', '10'], _.ary(parseInt, 1));
|
||||||
|
* // => [6, 8, 10]
|
||||||
|
*/
|
||||||
|
function ary(func, n, guard) {
|
||||||
|
if (guard && isIterateeCall(func, n, guard)) {
|
||||||
|
n = null;
|
||||||
|
}
|
||||||
|
n = n == null ? func.length : (+n || 0);
|
||||||
|
return createWrapper(func, ARY_FLAG, null, null, null, null, null, n);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function that invokes `func`, with the `this` binding and arguments
|
* Creates a function that invokes `func`, with the `this` binding and arguments
|
||||||
* of the created function, while it is called less than `n` times. Subsequent
|
* of the created function, while it is called less than `n` times. Subsequent
|
||||||
@@ -10044,6 +10082,7 @@
|
|||||||
|
|
||||||
// Add functions that return wrapped values when chaining.
|
// Add functions that return wrapped values when chaining.
|
||||||
lodash.after = after;
|
lodash.after = after;
|
||||||
|
lodash.ary = ary;
|
||||||
lodash.assign = assign;
|
lodash.assign = assign;
|
||||||
lodash.at = at;
|
lodash.at = at;
|
||||||
lodash.before = before;
|
lodash.before = before;
|
||||||
|
|||||||
111
test/test.js
111
test/test.js
@@ -879,6 +879,114 @@
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
QUnit.module('lodash.ary');
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
function fn() {
|
||||||
|
return slice.call(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should cap the numer of params provided to `func`', 2, function() {
|
||||||
|
var actual = _.map(['6', '8', '10'], _.ary(parseInt, 1));
|
||||||
|
deepEqual(actual, [6, 8, 10]);
|
||||||
|
|
||||||
|
var capped = _.ary(fn, 2);
|
||||||
|
deepEqual(capped('a', 'b', 'c', 'd'), ['a', 'b']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work when provided less than the capped numer of arguments', 1, function() {
|
||||||
|
var capped = _.ary(fn, 3);
|
||||||
|
deepEqual(capped('a'), ['a']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work when combined with other methods that use metadata', 2, function() {
|
||||||
|
var array = ['a', 'b', 'c'],
|
||||||
|
includes = _.curry(_.rearg(_.ary(_.includes, 2), 1, 0), 2);
|
||||||
|
|
||||||
|
strictEqual(includes('b')(array, 2), true);
|
||||||
|
|
||||||
|
if (!isNpm) {
|
||||||
|
includes = _(_.includes).ary(2).rearg(1, 0).curry(2).value();
|
||||||
|
strictEqual(includes('b')(array, 2), true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
QUnit.module('lodash.rearg');
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
function fn() {
|
||||||
|
return slice.call(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should reorder arguments provided to `func`', 1, function() {
|
||||||
|
var rearged = _.rearg(fn, [2, 0, 1]);
|
||||||
|
deepEqual(rearged('b', 'c', 'a'), ['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work with repeated indexes', 1, function() {
|
||||||
|
var rearged = _.rearg(fn, [1, 1, 1]);
|
||||||
|
deepEqual(rearged('c', 'a', 'b'), ['a', 'a', 'a']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should use `undefined` for nonexistent indexes', 1, function() {
|
||||||
|
var rearged = _.rearg(fn, [1, 4]);
|
||||||
|
deepEqual(rearged('b', 'a', 'c'), ['a', undefined, 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should use `undefined` for non-index values', 1, function() {
|
||||||
|
var values = _.reject(empties, function(value) {
|
||||||
|
return value === 0 || _.isArray(value);
|
||||||
|
}).concat(-1, 1.1);
|
||||||
|
|
||||||
|
var expected = _.map(values, _.constant([undefined, 'b', 'c']));
|
||||||
|
|
||||||
|
var actual = _.map(values, function(value) {
|
||||||
|
var rearged = _.rearg(fn, [value]);
|
||||||
|
return rearged('a', 'b', 'c');
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(actual, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not rearrange arguments when no indexes are provided', 2, function() {
|
||||||
|
var rearged = _.rearg(fn);
|
||||||
|
deepEqual(rearged('a', 'b', 'c'), ['a', 'b', 'c']);
|
||||||
|
|
||||||
|
rearged = _.rearg(fn, [], []);
|
||||||
|
deepEqual(rearged('a', 'b', 'c'), ['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should accept multiple index arguments', 1, function() {
|
||||||
|
var rearged = _.rearg(fn, 2, 0, 1);
|
||||||
|
deepEqual(rearged('b', 'c', 'a'), ['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should accept multiple arrays of indexes', 1, function() {
|
||||||
|
var rearged = _.rearg(fn, [2], [0, 1]);
|
||||||
|
deepEqual(rearged('b', 'c', 'a'), ['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work with fewer indexes than arguments', 1, function() {
|
||||||
|
var rearged = _.rearg(fn, [1, 0]);
|
||||||
|
deepEqual(rearged('b', 'a', 'c'), ['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work on functions that have been rearged', 1, function() {
|
||||||
|
var rearged1 = _.rearg(fn, 2, 1, 0),
|
||||||
|
rearged2 = _.rearg(rearged1, 1, 0, 2);
|
||||||
|
|
||||||
|
deepEqual(rearged2('b', 'c', 'a'), ['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
QUnit.module('lodash.assign');
|
QUnit.module('lodash.assign');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
@@ -13649,6 +13757,7 @@
|
|||||||
|
|
||||||
var rejectFalsey = [
|
var rejectFalsey = [
|
||||||
'after',
|
'after',
|
||||||
|
'ary',
|
||||||
'backflow',
|
'backflow',
|
||||||
'before',
|
'before',
|
||||||
'bind',
|
'bind',
|
||||||
@@ -13739,7 +13848,7 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should throw a TypeError for falsey arguments', 21, function() {
|
test('should throw a TypeError for falsey arguments', 22, function() {
|
||||||
_.each(rejectFalsey, function(methodName) {
|
_.each(rejectFalsey, function(methodName) {
|
||||||
var expected = _.map(falsey, _.constant(true)),
|
var expected = _.map(falsey, _.constant(true)),
|
||||||
func = _[methodName];
|
func = _[methodName];
|
||||||
|
|||||||
Reference in New Issue
Block a user