mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-09 10:27:49 +00:00
Add _.consume and _.consumeRight and make _.compose an alias of _.consumeRight. [closes #667]
This commit is contained in:
106
lodash.js
106
lodash.js
@@ -5916,62 +5916,98 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function that is the composition of the provided functions,
|
* Creates a function that invokes the provided functions with the `this`
|
||||||
* where each function consumes the return value of the function that follows.
|
* binding of the create function, where each successive invocation consumes
|
||||||
* For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
|
* the return value of the previous.
|
||||||
* Each function is executed with the `this` binding of the composed function.
|
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
* @category Function
|
* @category Function
|
||||||
* @param {...Function} [funcs] Functions to compose.
|
* @param {...Function} [funcs] Functions to invoke.
|
||||||
* @returns {Function} Returns the new composed function.
|
* @returns {Function} Returns the new function.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* var realNameMap = {
|
* function add(x, y) {
|
||||||
* 'pebbles': 'penelope'
|
* return x + y;
|
||||||
* };
|
* }
|
||||||
*
|
*
|
||||||
* var format = function(name) {
|
* function square(n) {
|
||||||
* name = realNameMap[name.toLowerCase()] || name;
|
* return n * n;
|
||||||
* return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
|
* }
|
||||||
* };
|
|
||||||
*
|
*
|
||||||
* var greet = function(formatted) {
|
* var addSquare = _.consume(add, square);
|
||||||
* return 'Hiya ' + formatted + '!';
|
* addSquare(1, 2);
|
||||||
* };
|
* // => 9
|
||||||
*
|
|
||||||
* var welcome = _.compose(greet, format);
|
|
||||||
* welcome('pebbles');
|
|
||||||
* // => 'Hiya Penelope!'
|
|
||||||
*/
|
*/
|
||||||
function compose() {
|
function consume() {
|
||||||
var funcs = arguments,
|
var funcs = arguments,
|
||||||
length = funcs.length,
|
length = funcs.length;
|
||||||
index = length - 1;
|
|
||||||
|
|
||||||
if (!length) {
|
if (!length) {
|
||||||
return function() {};
|
return function() {};
|
||||||
}
|
}
|
||||||
while (length--) {
|
if (!arrayEvery(funcs, isFunction)) {
|
||||||
if (!isFunction(funcs[length])) {
|
throw new TypeError(FUNC_ERROR_TEXT);
|
||||||
throw new TypeError(FUNC_ERROR_TEXT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return function() {
|
return function() {
|
||||||
length = index;
|
var index = 0,
|
||||||
var result = funcs[length].apply(this, arguments);
|
result = funcs[index].apply(this, arguments);
|
||||||
|
|
||||||
while (length--) {
|
while (++index < length) {
|
||||||
result = funcs[length].call(this, result);
|
result = funcs[index].call(this, result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function which accepts one or more arguments of `func` that when
|
* This method is like `_.consume` except that it creates a function that
|
||||||
* invoked either executes `func` returning its result, if all `func` arguments
|
* invokes the provided functions from right to left.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf _
|
||||||
|
* @alias compose
|
||||||
|
* @category Function
|
||||||
|
* @param {...Function} [funcs] Functions to invoke.
|
||||||
|
* @returns {Function} Returns the new function.
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* function add(x, y) {
|
||||||
|
* return x + y;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* function square(n) {
|
||||||
|
* return n * n;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* var addSquare = _.consumeRight(square, add);
|
||||||
|
* addSquare(1, 2);
|
||||||
|
* // => 9
|
||||||
|
*/
|
||||||
|
function consumeRight() {
|
||||||
|
var funcs = arguments,
|
||||||
|
fromIndex = funcs.length - 1;
|
||||||
|
|
||||||
|
if (fromIndex < 0) {
|
||||||
|
return function() {};
|
||||||
|
}
|
||||||
|
if (!arrayEvery(funcs, isFunction)) {
|
||||||
|
throw new TypeError(FUNC_ERROR_TEXT);
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
var index = fromIndex,
|
||||||
|
result = funcs[index].apply(this, arguments);
|
||||||
|
|
||||||
|
while (index--) {
|
||||||
|
result = funcs[index].call(this, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a function that accepts one or more arguments of `func` that when
|
||||||
|
* called either invokes `func` returning its result if all `func` arguments
|
||||||
* have been provided, or returns a function that accepts one or more of the
|
* have been provided, or returns a function that accepts one or more of the
|
||||||
* remaining `func` arguments, and so on. The arity of `func` can be specified
|
* remaining `func` arguments, and so on. The arity of `func` can be specified
|
||||||
* if `func.length` is not sufficient.
|
* if `func.length` is not sufficient.
|
||||||
@@ -9303,7 +9339,8 @@
|
|||||||
lodash.chain = chain;
|
lodash.chain = chain;
|
||||||
lodash.chunk = chunk;
|
lodash.chunk = chunk;
|
||||||
lodash.compact = compact;
|
lodash.compact = compact;
|
||||||
lodash.compose = compose;
|
lodash.consume = consume;
|
||||||
|
lodash.consumeRight = consumeRight;
|
||||||
lodash.constant = constant;
|
lodash.constant = constant;
|
||||||
lodash.countBy = countBy;
|
lodash.countBy = countBy;
|
||||||
lodash.create = create;
|
lodash.create = create;
|
||||||
@@ -9384,6 +9421,7 @@
|
|||||||
|
|
||||||
// add aliases
|
// add aliases
|
||||||
lodash.collect = map;
|
lodash.collect = map;
|
||||||
|
lodash.compose = consumeRight;
|
||||||
lodash.each = forEach;
|
lodash.each = forEach;
|
||||||
lodash.eachRight = forEachRight;
|
lodash.eachRight = forEachRight;
|
||||||
lodash.extend = assign;
|
lodash.extend = assign;
|
||||||
|
|||||||
64
test/test.js
64
test/test.js
@@ -1722,52 +1722,64 @@
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
QUnit.module('lodash.compose');
|
QUnit.module('lodash.consumeRight');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
test('should create a function that is the composition of the provided functions', 1, function() {
|
test('should be aliased', 1, function() {
|
||||||
var realNameMap = {
|
strictEqual(_.compose, _.consumeRight);
|
||||||
'pebbles': 'penelope'
|
});
|
||||||
};
|
}());
|
||||||
|
|
||||||
var format = function(name) {
|
/*--------------------------------------------------------------------------*/
|
||||||
name = realNameMap[name.toLowerCase()] || name;
|
|
||||||
return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
var greet = function(formatted) {
|
QUnit.module('consume methods');
|
||||||
return 'Hiya ' + formatted + '!';
|
|
||||||
};
|
|
||||||
|
|
||||||
var welcome = _.compose(greet, format);
|
_.each(['consume', 'consumeRight'], function(methodName) {
|
||||||
strictEqual(welcome('pebbles'), 'Hiya Penelope!');
|
var func = _[methodName],
|
||||||
|
isConsume = methodName == 'consume';
|
||||||
|
|
||||||
|
test('`_.' + methodName + '` should create a function that consumes the output of the provided functions', 1, function() {
|
||||||
|
function add(x, y) {
|
||||||
|
return x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
function square(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixed(n) {
|
||||||
|
return n.toFixed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var consumer = isConsume ? func(add, square, fixed) : func(fixed, square, add);
|
||||||
|
strictEqual(consumer(1, 2), '9.0');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return a new function', 1, function() {
|
test('`_.' + methodName + '` should return a new function', 1, function() {
|
||||||
notStrictEqual(_.compose(_.noop), _.noop);
|
notStrictEqual(func(_.noop), _.noop);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return a noop function when no arguments are provided', 2, function() {
|
test('`_.' + methodName + '` should return a noop function when no arguments are provided', 2, function() {
|
||||||
var composed = _.compose();
|
var consumer = func();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
strictEqual(composed(), undefined);
|
strictEqual(consumer(), undefined);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
ok(false);
|
ok(false);
|
||||||
}
|
}
|
||||||
notStrictEqual(composed, _.noop);
|
notStrictEqual(consumer, _.noop);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return a wrapped value when chaining', 1, function() {
|
test('`_.' + methodName + '` should return a wrapped value when chaining', 1, function() {
|
||||||
if (!isNpm) {
|
if (!isNpm) {
|
||||||
var actual = _(_.noop).compose();
|
var actual = _(_.noop)[methodName]();
|
||||||
ok(actual instanceof _);
|
ok(actual instanceof _);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipTest();
|
skipTest();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}());
|
});
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -12060,6 +12072,8 @@
|
|||||||
'before',
|
'before',
|
||||||
'bind',
|
'bind',
|
||||||
'compose',
|
'compose',
|
||||||
|
'consume',
|
||||||
|
'consumeRight',
|
||||||
'curry',
|
'curry',
|
||||||
'curryRight',
|
'curryRight',
|
||||||
'debounce',
|
'debounce',
|
||||||
@@ -12143,13 +12157,13 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should throw a TypeError for falsey arguments', 17, function() {
|
test('should throw a TypeError for falsey arguments', 19, 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];
|
||||||
|
|
||||||
var actual = _.map(falsey, function(value, index) {
|
var actual = _.map(falsey, function(value, index) {
|
||||||
var pass = !index && methodName == 'compose';
|
var pass = !index && /^(?:compose|consume(Right)?)$/.test(methodName);
|
||||||
try {
|
try {
|
||||||
index ? func(value) : func();
|
index ? func(value) : func();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user