The source of curry and the name of the mathematician Haskell Curry (the programming language Haskell is also named under his name).
Gerty is often called partial evaluation, the meaning of the function is to pass the parameters, each pass the argument after the application of parameters, and return a more specific function to accept the remaining parameters, which can be nested multi-layer such as the acceptance of the partial parameter function, until the final result returned.
Therefore, the process of gerty is to gradually transfer the parameters, gradually narrowing the scope of application of the function, and gradually solve the process.
To curry a sum function
According to the step-by-step evaluation, let's look at a simple example
var concat3words = function (A, B, c) {return
a+b+c;
};
var concat3wordscurrying = function (a) {return
function (b) {return
function (c) {return
a+b+c;
};
};
};
Console.log (Concat3words ("foo", "Bar", "Baza")); Foo bar baza
console.log (concat3wordscurrying ("foo")); [Function]
As you can see, concat3wordscurrying ("foo") is a function, each call returns a new function that accepts another call, and then returns a new function until the result is returned, the distribution is solved, and the layer is progressive. (PS: This utilizes the features of closures)
So now we go further, if you require more than 3 parameters to be passed, you can pass any number of parameters, when the parameters are not passed output?
Let's start with a common implementation:
var add = function (items) {return
items.reduce (function (a,b) {return
a+b
});
But if you need to multiply each number by 10 and then add it, then:
var add = function (Items,multi) {return
Items.map (function (item) {return
item*multi;
}). Reduce (function (A, b) {return
A + b
});
Fortunately, with the map and reduce functions, if you follow this pattern and now you want to add 1 to each item, then we need to replace the function in the map.
Here's a look at the Gerty implementation:
var adder = function () {
var _args = [];
return function () {
if (arguments.length = 0) {return
_args.reduce (function (A, b) {return
a + b;
}) ;
}
[].push.apply (_args, [].slice.call (arguments));
return arguments.callee;
}
;
var sum = adder ();
Console.log (sum); Function
sum (100,200); The calling form is flexible, one call can be entered with a single parameter or more, and a chained call of sum is supported
;
Console.log (sum ()); 1000 (plus total calculation)
The above adder is a gerty function that returns a new function that receives a new parameter that can be divided into batches and deferred to the last calculation.
General functions of the Gerty
More typically, Gerty will encapsulate the last calculation into a function, then pass the function as a parameter into the Gerty function, which is clear and flexible.
For example, with each item multiplied by 10, we can pass the handler function as a parameter:
var currying = function (fn) {
var _args = [];
return function () {
if (arguments.length = 0) {return
fn.apply (this, _args);
}
Array.prototype.push.apply (_args, [].slice.call (arguments));
return arguments.callee;
}
;
var multi=function () {
var total = 0;
for (var i = 0, c; c = arguments[i++];) {Total
= c;
}
return total;
};
var sum = currying (multi);
SUM (100,200) (+);
Sum ();
Console.log (sum ()); 1000 (only true when blank calls are counted)
So sum = currying (multi), the call is very clear, the use of the effect is also called gorgeous, such as to add multiple values, you can take multiple values as a parameter sum (1,2,3), can also support chained calls, SUM (1) (2) (3)
The basis of the curry
The above code is actually a higher order function (High-order function), which is a function of the operation function that receives one or more functions as arguments and returns a new function. In addition, it relies on the characteristics of the closure to hold the parameters entered in the middle process. That
Functions can be passed as arguments
function can be used as the return value of a function
Closed Bag
The role of the curry
Deferred calculation. The example above is already very low.
Parameter reuse. When the same function is called more than once, and the majority of the arguments passed are the same, the function may be a good candidate for Gerty.
Create a function dynamically. This can be done after the partial calculation of the results, on this basis dynamically generated new functions to deal with the subsequent business, so that the redundant calculation is omitted. Alternatively, you can dynamically create a new function by using a subset of the parameters that will be passed in to the calling function, and the new function saves the repeated incoming arguments (not every time in the future). For example, the event browser adds an auxiliary method for an event:
var addevent = function (el, type, FN, capture) {
if (window.addeventlistener) {
El.addeventlistener type, Function (e) {
fn.call (el, E);
}, capture);
} else if (window.attachevent) {
el.attachevent ("on" + type, Function (e) {
fn.call (el, E);
});
Execute every time you add event handling if...else ..., in fact, in a browser as long as a decision on it, the results based on a decision after the dynamic generation of new functions, you do not have to recalculate.
var addevent = (function () {
if (window.addeventlistener) {return
function (el, Stype, FN, capture) {
El.addeventlistener (stype, function (e) {
fn.call (el, E);
}, (capture);}
;
} else if ( window.attachevent) {return
function (el, Stype, FN, capture) {
el.attachevent (' on ' + stype, function (e) {
Fn.call (EL, E);}
);};}
This example, the first time if...else ... After judgment, a partial calculation is completed, and a new function is dynamically created to handle the parameters passed in later, which is a typical gerty.
Function.prototype.bind method is also the application of Gerty
Unlike the Call/apply method, the Bind method sets the first argument to the context in which the function executes, and the other arguments are passed to the calling method (the body of the function itself is not executed, can be seen as deferred execution), and dynamic creation returns a new function, which is consistent with the characteristics of Cory.
var foo = {x:888};
var bar = function () {
console.log (this.x);
Bind (foo); Bind
Bar (); 888
The following is a simulation of a bind function that Testbind creates and returns a new function that binds the function that really wants to perform a business to the context in which the actual argument is passed, deferred execution.
Function.prototype.testBind = function (scope) {
var fn = this; This refers to a function that invokes the Testbind method, return
function () {return
fn.apply (scope);
}
;
var testbindbar = Bar.testbind (foo); Binding foo, delaying execution of
Console.log (Testbindbar); function (visible, a new function that is returned after bind is a deferred execution)
Testbindbar (); 888
Here you should pay attention to the understanding of this in prototype.
The above in-depth analysis of JavaScript functions currying Gerty is a small series to share all the content, hope to give you a reference, but also hope that we support the cloud-dwelling community.