Update and add tests for fp convert method.

This commit is contained in:
John-David Dalton
2016-03-04 00:55:59 -08:00
parent f6df126c43
commit 4debf155d7
4 changed files with 91 additions and 57 deletions

View File

@@ -41,10 +41,12 @@ function baseConvert(util, name, func, options) {
}; };
var forceRearg = ('rearg' in options) && options.rearg, var forceRearg = ('rearg' in options) && options.rearg,
placeholder = isLib ? func : fallbackHolder; placeholder = isLib ? func : fallbackHolder,
pristine = isLib ? func.runInContext() : undefined;
var helpers = isLib ? func : { var helpers = isLib ? func : {
'ary': util.ary, 'ary': util.ary,
'assign': util.assign,
'clone': util.clone, 'clone': util.clone,
'curry': util.curry, 'curry': util.curry,
'forEach': util.forEach, 'forEach': util.forEach,
@@ -58,6 +60,7 @@ function baseConvert(util, name, func, options) {
}; };
var ary = helpers.ary, var ary = helpers.ary,
assign = helpers.assign,
clone = helpers.clone, clone = helpers.clone,
curry = helpers.curry, curry = helpers.curry,
each = helpers.forEach, each = helpers.forEach,
@@ -226,8 +229,19 @@ function baseConvert(util, name, func, options) {
var wrap = function(name, func) { var wrap = function(name, func) {
name = mapping.aliasToReal[name] || name; name = mapping.aliasToReal[name] || name;
var wrapper = wrappers[name]; var wrapper = wrappers[name];
var convert = function(options) {
var newUtil = isLib ? pristine.runInContext() : helpers,
newFunc = isLib ? pristine[name] : func,
newOptions = assign(assign({}, config), options);
return baseConvert(newUtil, name, newFunc, newOptions);
};
if (wrapper) { if (wrapper) {
return wrapper(func); var result = wrapper(func);
result.convert = convert;
return result;
} }
var wrapped = func; var wrapped = func;
if (config.immutable) { if (config.immutable) {
@@ -241,7 +255,6 @@ function baseConvert(util, name, func, options) {
wrapped = immutWrap(func, cloneByPath); wrapped = immutWrap(func, cloneByPath);
} }
} }
var result;
each(aryMethodKeys, function(aryKey) { each(aryMethodKeys, function(aryKey) {
each(mapping.aryMethod[aryKey], function(otherName) { each(mapping.aryMethod[aryKey], function(otherName) {
if (name == otherName) { if (name == otherName) {
@@ -275,13 +288,16 @@ function baseConvert(util, name, func, options) {
}); });
result || (result = wrapped); result || (result = wrapped);
if (result == func) {
result = function() {
return func.apply(this, arguments);
};
}
result.convert = convert;
if (mapping.placeholder[name]) { if (mapping.placeholder[name]) {
setPlaceholder = true; setPlaceholder = true;
func.placeholder = result.placeholder = placeholder; func.placeholder = result.placeholder = placeholder;
} }
result.convert = function(options) {
return baseConvert(util, name, func, options);
};
return result; return result;
}; };

View File

@@ -14,7 +14,7 @@ In a browser:
In Node.js: In Node.js:
```js ```js
// Load the fp build. // Load the fp build.
var _ = require('lodash/fp'); var fp = require('lodash/fp');
// Load a method category. // Load a method category.
var object = require('lodash/fp/object'); var object = require('lodash/fp/object');
@@ -25,27 +25,34 @@ var extend = require('lodash/fp/extend');
## Convert ## Convert
Although `lodash/fp` & its method modules come pre-converted, there are times when Although `lodash/fp` & its method modules come pre-converted, there are times
you may want to customize the conversion. Thats when the `convert` method comes in handy. when you may want to customize the conversion. Thats when the `convert` method
comes in handy.
```js ```js
// Disable capping of the iteratee arguments so it is possible to access // Every option is `true` by default.
// the `key` argument var mapValues = fp.mapValues.convert({
var mapValuesWithKey = require("lodash/fp/mapValues").convert({cap: false}); // Specify capping iteratee arguments.
'cap': true,
// Specify currying.
'curry': true,
// Specify fixed arity.
'fixed': true,
// Specify immutable operations.
'immutable': true,
// Specify rearranging arguments.
'rearg': true
});
// Disable capping of iteratee arguments to access the `key` param.
var mapValuesWithKey = fp.mapValues.convert({ 'cap': false });
mapValuesWithKey(function(value, key) { mapValuesWithKey(function(value, key) {
if (key === "foo") { return key == 'a' ? -1 : value;
return -1; })({ 'a': 1, 'b': 1 });
} // => { 'a': -1, 'b': 1 }
return value;
}, {foo: 1, bar: 1});
// => {foo: -1, bar: 1}
``` ```
It's also possible to use the convert function directly to convert functions or Its also possible to use the convert module directly for manual conversions.
objects manually.
```js ```js
var convert = require('lodash/fp/convert'); var convert = require('lodash/fp/convert');
@@ -62,31 +69,6 @@ var fp = convert({
var fp = convert(lodash.runInContext()); var fp = convert(lodash.runInContext());
``` ```
Its customizable too.
```js
// Every option is `true` by default.
var filter = convert('filter', _.filter, {
// Specify capping iteratee arguments.
'cap': true,
// Specify currying.
'curry': true,
// Specify fixed arity.
'fixed': true,
// Specify immutable operations.
'immutable': true,
// Specify rearranging arguments.
'rearg': true
});
// Specify `cap` of `false` to create a function that doesnt cap iteratee arguments.
var filter = convert('filter', _.filter, { 'cap': false });
filter(function(value, index) {
return index % 2 == 0;
})(['a', 'b', 'c']);
// => ['a', 'c']
```
## Mapping ## Mapping
Immutable auto-curried iteratee-first data-last methods sound great, but what Immutable auto-curried iteratee-first data-last methods sound great, but what

View File

@@ -1,5 +1,6 @@
module.exports = { module.exports = {
'ary': require('../ary'), 'ary': require('../ary'),
'assign': require('../_baseAssign'),
'clone': require('../clone'), 'clone': require('../clone'),
'curry': require('../curry'), 'curry': require('../curry'),
'forEach': require('../_arrayEach'), 'forEach': require('../_arrayEach'),

View File

@@ -67,6 +67,14 @@
}; };
}()); }());
var allFalseOptions = {
'cap': false,
'curry': false,
'fixed': false,
'immutable': false,
'rearg': false
};
var fp = root.fp var fp = root.fp
? (fp = _.noConflict(), _ = root._, fp) ? (fp = _.noConflict(), _ = root._, fp)
: convert(_.runInContext()); : convert(_.runInContext());
@@ -95,17 +103,9 @@
console.log('Running lodash/fp tests.'); console.log('Running lodash/fp tests.');
} }
QUnit.module('convert'); QUnit.module('convert module');
(function() { (function() {
var allFalseOptions = {
'cap': false,
'curry': false,
'fixed': false,
'immutable': false,
'rearg': false
};
QUnit.test('should work when given an object', function(assert) { QUnit.test('should work when given an object', function(assert) {
assert.expect(2); assert.expect(2);
@@ -274,6 +274,41 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('convert method');
(function() {
QUnit.test('should work when given an object', function(assert) {
assert.expect(3);
var array = [1, 2, 3, 4],
remove = fp.remove.convert(allFalseOptions);
var actual = remove(array, function(n, index) {
return index % 2 == 0;
});
assert.deepEqual(array, [2, 4]);
assert.deepEqual(actual, [1, 3]);
assert.deepEqual(remove(), []);
});
QUnit.test('should extend existing configs', function(assert) {
assert.expect(2);
var array = [1, 2, 3, 4],
remove = fp.remove.convert({ 'cap': false }).convert({ 'rearg': false });
var actual = remove(array)(function(n, index) {
return index % 2 == 0;
});
assert.deepEqual(array, [1, 2, 3, 4]);
assert.deepEqual(actual, [2, 4]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('method arity checks'); QUnit.module('method arity checks');
(function() { (function() {