Principle and function analysis of Javascript Corritization

  • 2021-09-04 23:13:38
  • OfStack

Functional programming is a popular programming paradigm nowadays, which 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 and Clojure all support functional programming.

This programming idea covers three important concepts:

Pure function Currification Higher order function

And this article mainly wants to explain the concept of Corrigenization to everyone.

What is Corrigenization

First, let's look at an example:

function sum(a, b, c) {
return a + b + c;
}
//Call
sum(1, 2, 3); // 6

The above function realizes the addition of a, b and c parameters, and rewrites them into Coriolian functions 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

Currization is the process of transforming a function with more parameters into a function with fewer parameters.

Let's take a step-by-step look at what the Coriolis function above does. First, step 1 calls sum (1). At this time, the variable sum1 is equivalent to:

sum1 = function(b) {
return function(c) {
//Note that the variable a exists in the closure and can be called, a = 1
return a + b + c;
}
}

Then call sum1 (2), where assigning a value to the variable sum2 is equivalent to:

sum2 = function(c) {
//The variables a, b are all in closures, a = 1, b = 2
return a + b + c;
}

Finally, call sum2 (3) and return 1 + 2 + 3 result 6;

This is the simplest Corey function, isn't it very simple?

The role of Corey function

Then the problem comes. The above rewritten Coriolization function has a lot more code than the original function, and it is not as easy to understand as the original function. What's the use of Coriolization function?

It is true that the Currification function does look bloated and impractical here, but it is very useful in many scenarios, and even many people have inadvertently used the Currification function. Give a simple example:

Suppose we have a batch of cuboids, and we need to calculate the volume of these cuboids and implement the following function:


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);

If we calculate the volume function of cuboids as above, we will find that there are many cuboids with the same length. We will use Coriere function to realize 1:


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 above, by implementing an len200 function, we deal with 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() {
  console.log(' Print only 1 Times ');
});
onceConsole();
onceConsole();

As above, we implemented an execOnce function, which accepts a function parameter and then returns a function. The variable flag exists in the closure to judge whether the returned function has been executed. onceConsole is equivalent to:


let onceConsole = function() {
 if (flag) {
     (function() {
    console.log(' Print only 1 Times ');
   })()
   flag = false;
  }
}

This is also a simple application of Corey function.

Realization of General Corey Function

Since Coriolis function is so practical, can we realize a general Coriolis function? The so-called general, that is to say, the function parameters can be converted into a Coriolian function, look at the first version of the implementation of the code:


 //  No. 1 1 Version 
var curry = function (fn) {
 var args = [].slice.call(arguments, 1);
 return function() {
  var newArgs = args.concat([].slice.call(arguments));
  return fn.apply(null, newArgs);
 };
};
 function add(a, b) {
  return a + b;
 }

var addFun = curry(add, 1, 2);
addFun() // 3
// Or 
var addOne = curry(add, 1);

As in the code above, we accept a function as an argument, then collect other arguments, and pass these arguments to this function argument 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 way, we will report an error:

var addFun = curry(function(a, b,c) {
return a + b + c;
}, 1);
addFun (2) (3); //Error addFun (...) is not a function

This seems to violate our principle of parameter reuse, and the improvement is as follows:


function curry(fn, args) {
 var length = fn.length;
 args = args || [];
 return function(...rest) {
  var _args = [...args, ...rest];
  return _args.length < length
   ? curry.call(this, fn, _args)
  : fn.apply(this, _args);
 }
}
var fn = curry(function(a, b, c) {
 console.log(a + b + c);
});
fn('a', 'b', 'c'); // abc
fn('a', 'b')('c'); // abc
fn('a')('b')('c'); // abc

The above implementation is perfect, and the implementation of this tool function is summed up in one sentence:

The parameters of the function are stored by closure, and the function is executed when the number of parameters reaches 1.

Postscript

Corrification is based on closures. Not understanding closures may hinder the understanding of Corrification. I hope you can understand and understand Corrification of JavaScript through this article.


Related articles: