## lodash/fp The `lodash/fp` module promotes a more [functional programming](https://en.wikipedia.org/wiki/Functional_programming) (FP) friendly style by exporting an instance of `lodash` with its methods wrapped to produce immutable auto-curried iteratee-first data-last methods. ## Installation In a browser: ```html ``` In Node.js: ```js // Load the fp build. var fp = require('lodash/fp'); // Load a method category. var object = require('lodash/fp/object'); // Load a single method for smaller builds with browserify/rollup/webpack. var extend = require('lodash/fp/extend'); ``` ## Mapping Immutable auto-curried iteratee-first data-last methods sound great, but what does that really mean for each method? Below is a breakdown of the mapping used to convert each method. #### Capped Iteratee Arguments Iteratee arguments are capped to avoid gotchas with variadic iteratees. ```js // The `lodash/map` iteratee receives three arguments: // (value, index|key, collection) _.map(['6', '8', '10'], parseInt); // ➜ [6, NaN, 2] // The `lodash/fp/map` iteratee is capped at one argument: // (value) fp.map(parseInt)(['6', '8', '10']); // ➜ [6, 8, 10] ``` Methods that cap iteratees to one argument:
<%= toFuncList(_.keys(_.pickBy(mapping.iterateeAry, _.partial(_.eq, _, 1)))) %> Methods that cap iteratees to two arguments:
<%= toFuncList(_.keys(_.pickBy(mapping.iterateeAry, _.partial(_.eq, _, 2)))) %> The iteratee of `mapKeys` is capped to one argument: `(key)` #### Fixed Arity Methods have fixed arities to support auto-currying. ```js // `lodash/padStart` accepts an optional `chars` param. _.padStart('a', 3, '-') // ➜ '--a' // `lodash/fp/padStart` does not. fp.padStart(3)('a'); // ➜ ' a' fp.padCharsStart('-')(3)('a'); // ➜ '--a' ``` Methods with a fixed arity of one:
<%= toFuncList(_.difference(mapping.aryMethod[1], _.keys(mapping.skipFixed))) %> Methods with a fixed arity of two:
<%= toFuncList(_.difference(mapping.aryMethod[2], _.keys(mapping.skipFixed))) %> Methods with a fixed arity of three:
<%= toFuncList(_.difference(mapping.aryMethod[3], _.keys(mapping.skipFixed))) %> Methods with a fixed arity of four:
<%= toFuncList(_.difference(mapping.aryMethod[4], _.keys(mapping.skipFixed))) %> #### Rearranged Arguments Method arguments are rearranged to make composition easier. ```js // `lodash/filter` is data-first iteratee-last: // (collection, iteratee) var compact = _.partial(_.filter, _, Boolean); compact(['a', null, 'c']); // ➜ ['a', 'c'] // `lodash/fp/filter` is iteratee-first data-last: // (iteratee, collection) var compact = fp.filter(Boolean); compact(['a', null, 'c']); // ➜ ['a', 'c'] ``` ##### Most methods follow these rules A fixed arity of two has an argument order of:
<%= toArgOrder(mapping.aryRearg[2]) %> A fixed arity of three has an argument order of:
<%= toArgOrder(mapping.aryRearg[3]) %> A fixed arity of four has an argument order of:
<%= toArgOrder(mapping.aryRearg[4]) %> ##### Exceptions to the rules Methods that accept an array as their last or only argument:
<%= toFuncList(_.keys(mapping.methodSpread)) %> Methods with unchanged argument orders:
<%= toFuncList(_.keys(mapping.skipRearg)) %> Methods with custom argument orders:
<%= _.map(_.keys(mapping.methodRearg), methodName => { const orders = mapping.methodRearg[methodName]; return ' * `_.' + methodName + '` has an order of ' + toArgOrder(orders); }).join('\n') %> The iteratee of `reduceRight` has an argument order of: `(b, a)` #### New Methods Not all variadic methods have corresponding new method variants. Feel free to [request](https://github.com/lodash/lodash/blob/master/.github/CONTRIBUTING.md#feature-requests) any additions. Methods created to accommodate Lodash’s variadic methods:
<%= toFuncList(_.keys(mapping.remap)) %> #### Aliases There are <%= _.size(mapping.aliasToReal) %> method aliases:
<%= _.map(_.keys(mapping.aliasToReal).sort(), alias => { const realName = mapping.aliasToReal[alias]; return ' * `_.' + alias + '` is an alias of `_.' + realName + '`'; }).join('\n') %> ## Placeholders The placeholder argument, which defaults to `_`, may be used to fill in method arguments in a different order. Placeholders are filled by the first available arguments of the curried returned function. ```js // The equivalent of `2 > 5`. _.gt(2)(5); // ➜ false // The equivalent of `_.gt(5, 2)` or `5 > 2`. _.gt(_, 2)(5); // ➜ true ``` ## Chaining The `lodash/fp` module **does not** convert chain sequence methods. See [Izaak Schroeder’s article](https://medium.com/making-internets/why-using-chain-is-a-mistake-9bc1f80d51ba) on using functional composition as an alternative to method chaining. ## Convert Although `lodash/fp` & its method modules come pre-converted, there are times when you may want to customize the conversion. That’s when the `convert` method comes in handy. ```js // Every option is `true` by default. var _fp = fp.convert({ // 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 }); // The `convert` method is available on each method too. var mapValuesWithKey = fp.mapValues.convert({ 'cap': false }); // Here’s an example of disabling iteratee argument caps to access the `key` param. mapValuesWithKey(function(value, key) { return key == 'a' ? -1 : value; })({ 'a': 1, 'b': 1 }); // => { 'a': -1, 'b': 1 } ``` Manual conversions are also possible with the `convert` module. ```js var convert = require('lodash/fp/convert'); // Convert by name. var assign = convert('assign', require('lodash.assign')); // Convert by object. var fp = convert({ 'assign': require('lodash.assign'), 'chunk': require('lodash.chunk') }); // Convert by `lodash` instance. var fp = convert(lodash.runInContext()); ``` ## Tooling Use [eslint-plugin-lodash-fp](https://www.npmjs.com/package/eslint-plugin-lodash-fp) to help use `lodash/fp` more efficiently.