This is the 4th day of my participation in the August More Text Challenge.
preface
Both Collerization and partial functions are important concepts in functional programming, and today we are going to do a little bit different inverse Collerization.
But since it is anti-Cremation, let’s first understand its sister Cremation and partial functions.
Currie and partial functions
1.1 Mr Currie
Wikipedia says:
Currying, English: Currying, is a technique that converts a function that takes multiple arguments into a function that takes a single argument (the first argument of the original function), and returns a new function that takes the remaining arguments and returns a result.
The technique was named after logician Haskell Curry by Christopher Strachey, although it was invented by Moses Schnfinkel and Gottlob Frege.
Let’s look at an example, which is intuitive:
function sum(a, b, c) {
return a + b + c;
}
function currySum(a){
return function (b){
return function (c){
return a + b + c;
}
}
}
sum(1.2.3) / / 6
currySum(1) (2) (3) / / 6
Copy the code
To put it simply, there are two points:
-
More paragraphs to participate
-
A function that satisfies the condition that it executes the function and returns the result
1.1.1 the difficulty
The difficulty of the general Caulization function is how to know the length of function parameters. The commonly used means are as follows:
-
Function. The prototype. The length attribute for parameter length
The downside is that rest parameters are not counted in length.
The following code, which gets a length of 2, is the best fact.
function log(msg1, msg2, ... other){ console.log(msg1, msg2, ... other); }console.log(log.length); / / 2 Copy the code
-
Display the length of the incoming argument when currified
-
Of course, you can combine the two, a function default value is ok
function curry(fn, length = fn.length){ / /... } Copy the code
1.1.2 placeholder
The concept of having a placeholder after curryification means that I will pass this parameter in later.
Take a look at the official Lodash example.
var abc = function(a, b, c) {
return [a, b, c];
};
var curried = _.curry(abc);
// Curried with placeholders.
curried(1) (_,3) (2);
// => [1, 2, 3]
Copy the code
As for the implementation, the advanced version of Lodash.curry, the civilian version of JavaScript, has a special function called Currization.
1.2 partial function
Similar to Currization, simply understand that parameters are passed twice
- Fixed some parameters for the first time
- The remaining parameters are passed in a second time
Take a look at the underscore official example, which also has placeholders, but does not affect understanding.
var subtract = function(a, b) { return b - a; };
sub5 = _.partial(subtract, 5);
sub5(20); = >15
// Using a placeholder
subFrom20 = _.partial(subtract, _, 20);
subFrom20(5); = >15
Copy the code
As for implementation, advanced versions lodash.partial and underscore. Partial are JavaScript thematic partial functions
Up to this point, partial functions are similar in functionality to bind.
But that’s not the point of today, the point of today is anti-Corrification.
The curry
2.1 concept
Anti-cremation is the doctrine of taking something from someone else and using it.
Look at an example: we are commonly used to determine the data type of the Object. The prototype. ToString
function unCurry(fn) {
return function (context) {
return fn.apply(context, Array.prototype.slice.call(arguments.1)); }}// Do not use anti-Currization
Object.prototype.toString.call({}); // [object Object]
// Reverse Corrification
const toString = unCurry(Object.prototype.toString);
toString({}); // [object Object]
toString(() = >{});// [object Function]
toString(1); // [object Number]
Copy the code
2.2 implementation
2.2.1 Basic version: Easy to understand
function unCurry(fn) {
return function (context) {
return fn.apply(context, Array.prototype.slice.call(arguments.1)); }}Copy the code
2.2.2 Prototype version: Intrusion + convenience
Function.prototype.unCurry = function(){
var self = this;
return function(){
return Function.prototype.call.apply(self, arguments); }}Copy the code
This version invades the prototype, and I don’t like it. There is some convenience. There are two difficulties in understanding
-
Self = this self is equal to the function itself, so this is the staging function
-
Function.prototype.call.apply(self, arguments)
It’s a hassle to talk about, but look at the conversion below.
Function.prototype.call.apply(self, arguments) = = >Function.prototype.call.bind(self)(arguments)
==>
self.call(arguments)
==>
self.call(arguments[0].arguments[1-n]) // arguments[0] is the context for self function
Copy the code
It changes slightly when you use it
2.2.3 Prototype version 2
I’m not going to read into that, but you can make your own waves
Function.prototype.unCurry = function () {
return this.call.bind(this);
};
Copy the code
With ES6, does the following code also work?
Function.prototype.unCurry = function () {
return (. args) = > this.call(... args) };Copy the code
There are a variety of interesting ways to write this, for more details, see # Currified && Anti-Currified
2.3 Application Scenarios
Anti-corrification is a way of thinking, and its implementation can certainly be replaced by other schemes, but one more way of thinking, one more means.
2.3.1 Determine the data type
This was demonstrated in the demo above.
2.3.2 Array push (example in advanced programming)
const push = unCurry(Array.prototype.push);
const arr = [1.2.3];
push(arr, 4.5.6);
console.log(arr);
Copy the code
2.3.3 Copying an Array
const clone = unCurry(Array.prototype.slice);
var a = [1.2.3];
var b = clone(a);
console.log("a==b", a === b); // a==b false
console.log(a, b); // [1, 2, 3] [1, 2, 3]
Copy the code
2.3.4 Sending Events
const dispatch = unCurry(EventTarget.prototype.dispatchEvent);
window.addEventListener("event-x".(ev) = > {
console.log("event-x", ev.detail); // event-x ok
})
dispatch(window.new CustomEvent("event-x", { detail: "ok" }));
Copy the code
Detailed solution of JS function coriolization
Collerization and anti-Collerization
JavaScript thematic partial functions