Curry concept
The concept is simple:you can call a function with fewer arguments than it expects. It returns a function that takes the remaining arguments.
When you call a function, the passed argument is less than the expected number of functions, it returns a new function, and then calls the remaining parameters.
The number of arguments the function expects is actually the length
number returned by the function's properties. It does not include ( ES6
the remaining parameters).
A simple implementation
const add = x => y => x + y;const increment = add(1);const addTen = add(10);increment(2); // 3addTen(2); // 12
The key point is to use the closed package to collect the parameters .
What's the use of curry?
To tell the truth when I first studied, it was a few months ago, when I looked at the above code similar to the example, but also to understand concepts and principles. However, due to the state of being in a beginner's condition plus no experience in the baptism of large-scale projects (and now no 233) the development of inexperience, that the curry seems to have no special use. Plus 10 I directly add 10 good, plus 1 directly add 1 good, is not very convenient, but it is more troublesome, and therefore no attention. But above is just a simple example from which to explain the concept of curry, if its use is really just for the addition operation that is useless.
Here are a few examples from Mostly-adequate-guide chapter04:curring
const curry = require(‘lodash‘).curry;const match = curry((what, s) => s.match(what));const replace = curry((what, replacement, s) => s.replace(what, replacement));const filter = curry((f, xs) => xs.filter(f));const map = curry((f, xs) => xs.map(f));
Strategically place the data to be manipulated (String, Array) in the last parameter. By the time you use them, you'll understand why.
match(/r/g, ‘hello world‘); // [ ‘r‘ ]const hasLetterR = match(/r/g); // x => x.match(/r/g)hasLetterR(‘hello world‘); // [ ‘r‘ ]hasLetterR(‘just j and s and t etc‘); // nullfilter(hasLetterR, [‘rock and roll‘, ‘smooth jazz‘]); // [‘rock and roll‘]const removeStringsWithoutRs = filter(hasLetterR); // xs => xs.filter(x => x.match(/r/g))removeStringsWithoutRs([‘rock and roll‘, ‘smooth jazz‘, ‘drum circle‘]); // [‘rock androll‘, ‘drum circle‘]const noVowels = replace(/[aeiou]/ig); // (r,x) => x.replace(/[aeiou]/ig, r)const censored = noVowels(‘*‘); // x => x.replace(/[aeiou]/ig, ‘*‘)censored(‘Chocolate Rain‘); // ‘Ch*c*l*t* R**n‘
A new function that remembers these parameters can be obtained by collecting the parameters and passing the arguments that are less than the expected number of functions to the calling function.
This allows the code to be reused better by getting a new function that can be generalized through the passing of partial parameters.
Growth is limited, there is still no actual use of writing functional programming code, but also can really feel the value of it, but also a kind of progress.
Talk about the realization of curry
lodash.js curryvar abc = function(a, b, c) { return [a, b, c];};var curried = _.curry(abc);curried(1)(2)(3);// => [1, 2, 3]curried(1, 2)(3);// => [1, 2, 3]curried(1, 2, 3);// => [1, 2, 3]
Curry use
- The result is returned directly when the number of arguments we pass equals the expected number of the target function.
- When the passed argument is less than the expected function, a new function is returned, and the function now collects all the parameters passed in before, so you just pass in the remaining arguments.
Key points of implementation
- The number of expected functions is actually
function.length
- Returns a new function that contains the previous parameter. is actually using
Function.prototype.bind
Main function Realization:
function curry(targetfn) { // 预期参数个数 var numOfArgs = targetfn.length; return function curried() { // 参数个数小于的话把之前传入的参数收集起来,再次返回curry化的函数 if (arguments.length < numOfArgs) { return curried.bind(null, ...arguments); // without ES6 // return Function.prototype.bind.apply(curried, [null].concat(Array.prototype.slice.call(arguments))); } else { return targetfn.apply(null, arguments); } }}
This approach leverages closures, will targetfn
and numOfArgs
privatization, into internal variables
When the passed argument equals the numOfArgs
time, the calltargetfn
Reference
- Implementation of Lodash ' curry ' function
- Mostly-adequate-guide
Talking about functional programming curry