Functional programming is a popular programming paradigm today. It advocates passing functions as parameters and then returning a function without side effects. To put it bluntly, it is hoped that a function will only do one thing.
Programming languages such as JavaScript, Haskell, Clojure, etc. all support functional programming.
This programming idea covers three important concepts:
- Pure functions
- Curry
- Advanced functions
This article mainly wants to explain the concept of Curry to everyone.
What is Curricula
First, let’s take a look at an example:
function sum(a, b, c) {
return a + b + c;
}
// Call
sum(1, 2, 3); // 6
The above function implements the addition of three parameters a, b, and c and rewrites it into a Curry function as follows:
function sum(a) {
return function (b) {
return function(c) {
return a + b + c;
}
}
}
// Call
let sum1 = sum(1);
let sum2 = sum1(2);
sum2(3); // 6
Currying is the process of converting a function with more parameters into a function with fewer parameters.
Let's take a look at what the Curry function above does step by step. First, sum(1) is called in the first step. At this time, the variable sum1 is equivalent to:
sum1 = function(b) {
return function(c) {
// Note that the variable a exists in the closure at this time, and can be called, a = 1
return a + b + c;
}
}
Then call sum1(2), and at this time the value to the variable sum2 is equivalent to:
sum2 = function(c) {
// All variables a and b are in the closure, a = 1, b = 2
return a + b + c;
}
Finally, sum2(3) is called, returning the result 6 of 1 + 2 + 3;
This is the simplest Curry function, isn't it very simple?
The role of curry function
So the question is, the Curry function rewritten above has a lot more code than the original function, and it is not as easy to understand as the original function. What is the use of Curry function?
Indeed, the Curry function does look very bloated and not practical here, but it has a great effect in many scenarios, and many people even inadvertently use Curry function. Let's give a simple example:
Suppose we have a batch of cuboids, we need to calculate the volume of these cuboids and implement a function as follows:
function volume(length, width, height) { return length * width * height; } volume(200, 100, 200); volume(200, 150, 100); volume(200, 50, 80); volume(100, 50, 60);
As we calculate the volume function of the cuboid above, we will find that there are many cuboids of the same length. Let’s use the Curry function to implement it:
function volume(length, width, height) { return function(width) { return function(height) { return length * width * height; } } } let len200 = volume(200); len200(100)(200); len200(150)(100); len200(50)(80); volume(100)(50)(60);
As mentioned above, by implementing a len200 function, we uniformly process the volume of a cuboid with a length of 200, which realizes parameter multiplexing.
Let's give another example of executing a function only once:
function execOnce(fun) { let flag = true; return function() { if (flag) { fun && fun(); flag = false; } } } let onceConsole = execOnce(function() { ('Print once'); }); onceConsole(); onceConsole();
As above, we implement an execOnce function, which accepts a function parameter and then returns a function. The variable flag is present in the closure to determine whether the returned function has been executed. OnceConsole is equivalent to:
let onceConsole = function() { if (flag) { (function() { ('Print once'); })() flag = false; } }
This is also a simple application of Curry functions.
Implementation of general curry function
Since the Curry function is so practical, can we implement a general Curry function? The so-called generalization means that this function can convert function parameters into curry functions. Let’s take a look at the code implemented in the first version:
// First Editionvar curry = function (fn) { var args = [].(arguments, 1); return function() { var newArgs = ([].(arguments)); return (null, newArgs); }; }; function add(a, b) { return a + b; } var addFun = curry(add, 1, 2); addFun() // 3 //orvar addOne = curry(add, 1);
As mentioned above, we accept a function as a parameter, then collect other parameters, and pass these parameters to this function parameter for execution. But there is a problem with the above code, the parameters are not free enough. For example, if we want to call this, we will report an error:
var addFun = curry(function(a, b,c) {
return a + b + c;
}, 1);
addFun(2)(3); // Error addedFun(...) is not a function
This seems to violate our principle of parameter reuse and is improved as follows:
function curry(fn, args) { var length = ; args = args || []; return function(...rest) { var _args = [...args, ...rest]; return _args.length < length ? (this, fn, _args) : (this, _args); } } var fn = curry(function(a, b, c) { (a + b + c); }); fn('a', 'b', 'c'); // abc fn('a', 'b')('c'); // abc fn('a')('b')('c'); // abc
The above implementation is very complete, and the implementation of this tool function is summarized in one sentence:
Use closures to store the parameters of the function and execute the function when the parameters reach a certain number.
postscript
Curriculization is based on closures. Not understanding closures may hinder the understanding of Curriculization. I hope this article can help you understand and understand Curriculization in JavaScript.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.