| ## lodash/fp |
| |
| The `lodash/fp` module is an instance of `lodash` with its methods wrapped to |
| produce immutable auto-curried iteratee-first data-last methods. |
| |
| ## Installation |
| |
| In a browser: |
| ```html |
| <script src='path/to/lodash.js'></script> |
| <script src='path/to/lodash.fp.js'></script> |
| <script> |
| // Loading `lodash.fp.js` converts `_` to its fp variant. |
| _.defaults({ 'a': 2, 'b': 2 })({ 'a': 1 }); |
| // → { 'a: 1, 'b': 2 } |
| |
| // Use `noConflict` to restore the pre-fp variant. |
| var fp = _.noConflict(); |
| |
| _.defaults({ 'a': 1 }, { 'a': 2, 'b': 2 }); |
| // → { 'a: 1, 'b': 2 } |
| fp.defaults({ 'a': 2, 'b': 2 })({ 'a': 1 }); |
| // → { 'a: 1, 'b': 2 } |
| </script> |
| ``` |
| |
| 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:<br> |
| <%= toFuncList(_.keys(_.pickBy(mapping.iterateeAry, _.partial(_.eq, _, 1)))) %> |
| |
| Methods that cap iteratees to two arguments:<br> |
| <%= toFuncList(_.keys(_.pickBy(mapping.iterateeAry, _.partial(_.eq, _, 2)))) %> |
| |
| The iteratee of `mapKeys` is invoked with 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:<br> |
| <%= toFuncList(_.difference(mapping.aryMethod[1], _.keys(mapping.skipFixed))) %> |
| |
| Methods with a fixed arity of two:<br> |
| <%= toFuncList(_.difference(mapping.aryMethod[2], _.keys(mapping.skipFixed))) %> |
| |
| Methods with a fixed arity of three:<br> |
| <%= toFuncList(_.difference(mapping.aryMethod[3], _.keys(mapping.skipFixed))) %> |
| |
| Methods with a fixed arity of four:<br> |
| <%= 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:<br> |
| <%= toArgOrder(mapping.aryRearg[2]) %> |
| |
| A fixed arity of three has an argument order of:<br> |
| <%= toArgOrder(mapping.aryRearg[3]) %> |
| |
| A fixed arity of four has an argument order of:<br> |
| <%= toArgOrder(mapping.aryRearg[4]) %> |
| |
| ##### Exceptions to the rules |
| |
| Methods that accept an array of arguments as their second parameter:<br> |
| <%= toFuncList(_.keys(mapping.methodSpread)) %> |
| |
| Methods with unchanged argument orders:<br> |
| <%= toFuncList(_.keys(mapping.skipRearg)) %> |
| |
| Methods with custom argument orders:<br> |
| <%= _.map(_.keys(mapping.methodRearg), function(methodName) { |
| var orders = mapping.methodRearg[methodName]; |
| return ' * `_.' + methodName + '` has an order of ' + toArgOrder(orders); |
| }).join('\n') %> |
| |
| #### 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:<br> |
| <%= toFuncList(_.keys(mapping.remap)) %> |
| |
| #### Aliases |
| |
| There are <%= _.size(mapping.aliasToReal) %> method aliases:<br> |
| <%= _.map(_.keys(mapping.aliasToReal).sort(), function(alias) { |
| var 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()); |
| ``` |