How to use one sentence of code to realize the corrilization of functions in ES6

Time:2020-3-14

What’s Coriolis for? Let’s first look at the following function

Let store = (a, B, c) = > 
//The function is like a grocery store. Three soft coins are required for a bowl of qizai noodles: A, B, C (five parameters)

What’s the function currification? The process of buying noodles may be as follows:

Let curry store = curry (store) // the canteen just now has been curried

//Best case
Currystore (1,5,1) // boss, just right! No need to change. It's just seven yuan. Boss: "this is your qizai noodles" 

//Occasional situation
Let boss = currystore (5) // boss, take these five yuan first. I'll find out if there is one yuan. Boss:
Boss = boss (1) // with the boss, take this dollar first, and I'll find out if there is still a dollar left.. Boss:
Boss (1) // ha ha, it's finally found. Here it is! Boss: "this is your qizai noodles" 

Currystore (5) (1) (1) // equivalent to appeal

So here we can see that function currification can be used to slowly gather parameters and delay the execution of functions. (pay in installments first, then deliver!)

Do a question

Now, our goal is to implement a curry function to achieve the following effects:
When enough arguments are given, the function is executed. If the parameter is not enough, a new curry function will be returned.

Let curryplus = curry ((a, B, c) = > A + B + C) // here is a function with three parameters

Curryplus (1) (2) (3) // returns 6
Curryplus (1) (2,3) // returns 6
Curryplus (1,2) (3) // returns 6

Let x = curryplus (1) (2) // Hello, what are the two parameters? Returns a curry function (with two arguments already taken)
X (1) // return 4
X (2) // return 5

As a strong JS person, it’s not a problem to solve this problem with one line of code. The problem is that I’m not that strong…

So, let’s start with the earth method, orz

According to curry’s usage, the principle is that a function is returned. The number of parameters of this function is uncertain (you may take out two pieces of money at the same time), so we can use the writing method of indefinite parameters:

const curry = (fn) => {
  Return (... Args) = >
    //Pay for delivery
  }
}

The currierization function needs to remember that you have given him parameters. If not, it defaults to an empty array:

Const curry = (FN, arr = []) = >
  return (...args) =>{  
    //Pay for delivery
  }
}

Next, each time you call, you need to check whether the parameters are enough. If it is enough, execute FN. If not, a new curry function will be returned, and the existing parameters will be plugged into it:

const curry = ( fn, arr = []) => {
  return (...args) => { 

    //Determine whether the total number of parameters is equal to the number of FN parameters
    if([...arr, ...args].length === fn.length){
      Return FN (... Arr,... Args) // expand parameters, call FN
    }else{
      Return curry (FN, [... Arr,... Args]) // iterate, passing in all existing parameters
    }

  }
}

So far, we have implemented the curry function.

The next step is to see how to write more succinctly.
First of all, the middle code can be written as an immediate execution function, saving some… Arr,… Args:

const curry = ( fn, arr = []) => {
  return (...args) => { 

    Return (a = > {// A is an array
      if(a.length === fn.length) {
        return fn(...a)
      }else{
        return curry(fn, a)
      }
    }) ([... Arr,... Args]) // here, the ARR and args are spread out into an array and assigned to a

  }
}

The if statement can be reduced to a ternary expression, or many words can be omitted:


const curry = ( fn, arr = []) => {
  return (...args) => { 

    return ( a => { 

      return a.length === fn.length ? fn(...a) : curry(fn, a)

    })([...arr, ...args]) 

  }
}

Finally, since nothing is done in the function but return, you can use the most economical writing method of arrow function input = > output to save return and braces:

const curry = ( fn, arr = []) => {
  return (...args) => { 
    Return (a = > a.length = = = FN. Length? FN (... A): Curry (FN, a)) ([... Arr,... Args]) // collapse one layer first
  }
}

Refolding:

const curry = ( fn, arr = []) => {
  Return (... Args) = > (a = > a.length = = = FN. Length? FN (... A): Curry (FN, a)) ([... Arr,... Args]) // refold
}

I’m done. I’m done

const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args]) 
//The clothes are folded for you

Try it:

const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args])
let curryPlus = curry((a,b,c,d)=>a+b+c+d)

Curryplus (1,2,3) (4) // return 10
Curryplus (1,2) (4) (3) // return 10
Curryplus (1,2) (3,4) // return 10

Of course, the main function of currification function is to delay execution. The trigger condition for execution is not necessarily the equal number of parameters, but other conditions, such as when the number of parameters is 0. Then we need to slightly modify the curry function above:

const curry = ( fn, arr = []) => (...args) => ( (a,b) => b.length === 0? fn(...a) : curry(fn, a))([...arr, ...args],[...args])
let curryPlus = curry((...x)=>x.reduce((a,b)=>a+b))

Curryplus (1) // returns a function
Curryplus (1) (2) // returns a function

//Execute only when the number of parameters is 0
Curryplus (1) (2) (4) () // returns 7
Curryplus (1,2) (4) () // returns 7

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.