Function currying (black question mark face)? ? ? Currying (black question mark face)? ? ? Properly properly Chinese translation déjà vu; Let's take a look at what is the function currying:
Wikipedia explains that: the function of receiving a plurality of parameters into a single receiving parameter (first parameter of the first function) of the function, and returns the remaining parameters and accepts results returned in the art the new function. It was proposed by the mathematician Haskell Brooks Curry, and to curry name.
Concepts are often dry and difficult to understand, let's employer words to explain is this: if we are not sure how many parameters of this function, we can give it a pass parameters, and then by JS closure (Closed Should understand JS package, first closure learning knowledge come to learn this post https://www.cnblogs.com/dengyao-blogs/p/11475575.html ) returns to a function, in addition to the first internal function receives a parameter outside and outputs the remaining operating parameters, this is the function of currying;
Small example:
Scene (demand):
Well-known programmer overtime every day, or more, if we need to calculate a programmer overtime every day, our first reaction should be like this;
var overtime=0; function time(x){ return overtime+=x; } time(1); //1 time(2); //3 time(3); //6
The code above is certainly no problem, but you need to call every day count plus what time of day, a lot of trouble, and each function should be called once a certain operation, if the amount of data is huge, there may be risks of performance, then there lazy and can not be solutions to problems? some!
function time(x){ return function(y){ return x+y; } } var times=time(0); times(3);
But the above code is still a problem, a lot of time in the actual development of our parameters are uncertain, the above code is simple to achieve the basic operation curried, but for uncertain parameter case is not treated; therefore there limitations function parameters; however, we know from the above basic code function currying Gesha mean; when a function call is only allowed to pass in a parameter, and then returns through the inner closure function to process and receive the remaining argument, the function returns remember the time of the first parameter by means of the closure;
Let us transform what the code:
// first define a variable receive function var Overtime = ( function () { // definition of an array for receiving parameters var args = []; // here using a closure, internal and external function calls the function returns a return function () { // arguments browser built-in objects, specifically designed to receive parameters // If the length parameter is 0 i.e. no arguments IF (the arguments.length === 0 ) { // define variables for accumulating var time = 0 ; // cycle accumulation, and i is compared with the length of the args for ( var i = 0, L = args.length; i <L; i ++ ) { // for accumulation equivalent to args + Time = Time [i] Time + =args [I]; } // return the result of the accumulated return Time; // if arguments object parameter length is not zero, i.e., when the parameter has } the else { // empty array defined arguments parameter is added as an array entry, a first Old args argument as a change in this point, the second argument as arguments the remaining parameters were added to an empty array of the array [] .push.apply (args, arguments); } } }) (); Overtime ( 3.5 of); // The first day Overtime (4.5); // The next day Overtime (2.1); // day // ... console.log (Overtime ()); // 10.1
After the code transformation we have achieved function, but this is not a complete implementation of curried function, then we have to realize how complete it? Let us introduce a generic implementation:
Universal implementation:
// definition method currying, to pass a parameter var as currying = function (Fn) { // remaining empty parameter defines the number of assembly arguments object var args = []; // use the closure function returns a handle remaining parameters return function ( ) { // if arguments parameter length is 0, i.e. there is no remaining parameters IF (the arguments.length === 0 ) { // perform the above process return fn.apply ( the this , args) } the console.log (arguments) // If the parameter is not the length of the arguments is 0, i.e. there are remaining parameters // Adds an array on a prototype array of objects, Apply this point is used to change the args // a [] .slice.call (arguments) is added to the array array prototype Array.prototype.push.apply (args, []. Slice.call (arguments)) // args.push ([]. Slice.call (arguments)) the console.log (args) // returned here arguments.callee a closure function returns, the callee is a property of the object inside the arguments for function returns the object being performed return the arguments.callee } } // called here currying method and passing the add function, the result will be an internal function returns closure var s = as currying (the Add); // call the function of internal closure, when there will be parameter args parameter gradually added to the array, the parameter to be passed when there is no direct call // called when chaining support s (1) (2) (3 ) (); // can also pass a plurality of parameters disposable S (l, 2,3 ); the console.log (S ());
JS function currying advantages:
1. The delay may be calculated, i.e., if the incoming call parameters currying function is not invoked, will add to the parameters stored in the array, until there is no incoming call parameters;
2. multiplexing parameter, the parameter when calling the same function, and the vast majority of transmission is the same, then the function may be a good candidate for currying.
Relative things in the world, because there must be fruit, of course, there are bound to anti-currying currying;
Anti-currying ( uncurrying ), that is, with the meaning of currying opposite from the literal meaning is concerned; in fact the real anti-currying role is to expand the scope of application, that when we call a method, no need to consider the object itself in the design process, there is no such method, as long as the method is applicable to it, we can use; (this refers to dynamic languages duck type of thinking)
Before learning JS anti curried, we first learn about the type of thinking duck dynamic languages, to help us better understand:
Dynamic languages duck type thinking (Wikipedia explanation):
In programming, the type of duck (duck typing) is a dynamic type style.
In this style, a semantic object is active, not by inheritance from a particular class or implement particular interface, but is determined by the current set of methods and properties.
The name comes from the duck test the concept proposed by James Whitcomb Riley, "duck test" may put it this way:
When you see a bird walks like a duck, swim like a duck and quacks like a duck, then this bird can be called a duck.
Theoretical explanation often dry and difficult, and replaced with the words of people is: You are your mother's son / daughter, no matter whether you are the best, is beautiful, as long as you own your mother, then you are your mother's son / daughter; duck type is replaced, as long as you croak, walks like a duck, as long as you have a behavior like a duck, whether you are not a duck, then you can be called a duck;
There are a lot of ducks in Javascript reference types, such as when we were assigned to a variable, is clearly no need to consider the type of object, it is because of this, Javascript was more flexible, so that Javascript is a typical dynamic the type of language;
Anti-currying, we look at how the duck type of reference:
// add the function prototype object uncurring method Function.prototype.uncurring = function () { // change this point of // where this point is Array.prototype.push var Self = this ; // here for closure returns the internal function execution return function () { // create a variable, add and delete the first parameter in the prototype object above shift array // change this point is the array arguments var obj = Array.prototype.shift.call ( arguments); // finally executed and returns to the method of changing the directivity of obj i.e. arguments // and passing arguments as parameters return self.apply (obj, arguments); }; }; // add array prototype object methods uncurrying var Push = Array.prototype.push.uncurring (); // test // anonymous function self-executing ( function () { // Push is a function of the method here // equivalent parameters passed two arguments and 4 parameter, but the shift in the above methods remove the first parameter, where the parameter arguments are intercepted, so finally only actually passed in. 4 Push (arguments,. 4 ); the console.log (arguments); // [. 1, 2, 3, 4] // anonymous function calls from and into parameters 1,2,3 }) (1, 2, 3)
Here we can think about arguments is an object parameter receiving, there is no push method, then calls the push method arguments why can it?
This is because the code var push = Array.prototype.push.uncurring (); added to the push method a prototype object uncurring array method, and then performing a method anonymous function push (arguments, 4); when in a substantially the above method calls added to the prototype object of uncurring function returns a closure and method of internal functions are executed on the shift method will Array prototype object during the execution of the push (arguments, 4); the arguments taken, so in fact, the actual method call is a push (4), so the end result is [1,2,3,4]