JavaScript curry and Combinatorial functions ~

Source: Internet
Author: User

Do you think I'm a little bit of a blog post ? With the Curry and compose is what ghosts, how so magical. These two functions are also used primarily in the previous blog post.
Well, let's talk about it today. Curry and compose, these two things are very important for functional programming, and the basic example of a slightly more complex point involves both functions.
What is curry?
---function to curry. That's the thing. To give a simple example.

var _console=curry (function(x) {    console.log (x);}) _console (///Hello

In fact, in this role, first define the function, the post-pass parameter. _console saves this function and passes it to its arguments each time it is called. Isn't it simple?
Take a look at the implementation of Curry.

function Curry (FN) {    returnfunction(f) {        return  fn (f);    }}

Just to return a function so simple, here also involves the control inversion of FN, similar to Redux's dispatch, passed in dispatch using it.
So when the Curry function has 2 parameters, the curry is changed to:

function Curry (FN) {    returnfunction(f) {        return  function(g) {            return  fn (f,g);}}        }

So what are the 3 parameters?

function Curry (FN) {    returnfunction(f) {        returnfunction  (g) {            returnfunction(h) {                return  fn (f,g,h);            }        }        }}

So when I want to pass 2 parameters at a time, what if I pass 1 parameters?

function Curry (FN) {    returnfunction(f) {        returnfunction  (G,H) {                    return  fn (f,g,h);         }}}

So I changed my mind, I'm not sure how many parameters to pass each time, I'm not sure how many parameters are passed. What to do?

The automatic curry function, you will find that _.curry perfectly solves this problem, even when you pass an empty argument to ignore it.
Today we do not study the realization of _.curry, a great God can share the ~
We write a function of automatic curry today.
How to write? What's the idea? What's the difficulty of it?
First we need to know that the execution of the automatic curry function is the same as the execution of the ordinary curry function, that is, how many parameters return how many functions, take the length of the parameters of the function we know,

But the function is not an array, you can use a layer for loop return, can only change the idea, the function of the loop is recursive.
What's the difficulty of it?

We need to get his arguments every time we execute (), in recursion we can declare an external variable and store the arguments for each execution.

But this is not possible, because each recursive need to return a function, which means that you can not return to the previous layer. Then we can only pass the parameters of the execution as arguments to the function.
Direct Automatic Curry to you (copy testable)

functionCurry (FN, length, args) {length= Length | | Fn.length;//number of arguments to save the functionargs = args | | []; return function(){            var_args = Args.slice (0), Arg, I;  for(i = 0; i < arguments.length; i++) {//traversing _args, storing parameters for each executionarg =Arguments[i];               _args.push (ARG); }            if(_args.length <length) {                returnCurry.call ( This, FN, length, _args);//Call yourself recursively}Else {                returnFn.apply ( This, _args); }     }}

You can see that the number of return functions is resolved

if (_args.length < length) {    return curry.call (This, FN, length, _args);} Else {    return fn.apply (this, _args);}

_arg stores all parameters from start to present, if the argument is "enough" (a little knowledge, the number of length== function arguments of the function), call FN and pass all the arguments to him,

If not enough, continue recursion, recursion, the current parameters to the next layer of function.
The difficulty lies in the fact that each recursive return will have to traverse the current parameters, push it into the _args inside.
This also avoids the case of an empty argument when an empty argument is passed in, such as calling (). _args not change.

Do you have time to study the _.curry implementation process is not similar? -0-

Next protagonist,compose, this function in the FP called the combination function, it can put the parameters are all together, call. Flow- like.

function Compose (fn1,fn2) {    returnfunction(ARG) {     fn2 (fn1 (ARG))}    } var gen= Compose (function(b) {console.log (b);  Returnfunction(a) {Console.log (a);  return A + "be deal with a";}) Gen (//Hello hello deal with B;

Gen is like a plumbing, Gen ("Holle"); it's pouring water into the pipe.
It executes from the function on the left side of the compose, and Hello is the data stream, flowing through 2 functions. The return value of the first function is passed in to the second parameter to continue execution.
In functional programming, compose is an important part of avoiding imperative, and every function that FP wants to do is "pure", and the dirty stuff is given to the user. Combine each pure function into the compose, just like the Gulp pipe (), each function is like a plug-in to handle the data flow.
So I want to process the data flow from right to left,

function Compose (fn1,fn2) {    returnfunction(ARG) {     fn1 (fn2 (ARG))}    }

So like curry, I do not want to pass only 2 functions, I want to pass arbitrary function What to do?

Here we do not write automatic combination function, because in my analysis redux source of time found this function, redux help us write ~ We just to analyze it just fine.
First, the source code. Redux not as lodash as a function jump to jump, Lodash want to see only part of is not understand. The compose function of the redux (replication is testable).

functionCompose () { for(var_len = arguments.length, Funcs = Array (_len), _key = 0; _key < _len; _key++) {Funcs[_key]= Arguments[_key];//the parameters are copied into the Funcs array.       }      return function () {               if(Funcs.length = = 0) {          returnArguments.length <= 0? Undefined:arguments[0];//handle no parameters, return undefined        }         varlast = Funcs[funcs.length-1];//This is the last processing function        varRest = Funcs.slice (0,-1);//take apart the last remaining processing function        returnRest.reduceright (function(composed, F) {//executes the current handler each time the cardinality is passed in          returnf (composed);    }, last.apply (undefined, arguments)); //executes the last handler function, which returns the value as the base of reduce.       }; } 

His principle is simple, that is, all functions of arguments are executed once, the return value of the previous function is passed in. The Reduceright function of the array is cleverly used here.
You can change to reduce, and then this last change to first, which is done from left to right. The problem of processing order.

They are very useful, examples can look at the blog post ~ ~ point me .
To learn these two functions well, let's open the door to functional programming.

JavaScript curry and Combinatorial functions ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.