What is 'Currying'?

前端 未结 18 1295
遥遥无期
遥遥无期 2020-11-21 05:26

I\'ve seen references to curried functions in several articles and blogs but I can\'t find a good explanation (or at least one that makes sense!)

相关标签:
18条回答
  • 2020-11-21 06:12

    Curry can simplify your code. This is one of the main reasons to use this. Currying is a process of converting a function that accepts n arguments into n functions that accept only one argument.

    The principle is to pass the arguments of the passed function, using the closure (closure) property, to store them in another function and treat it as a return value, and these functions form a chain, and the final arguments are passed in to complete the operation.

    The benefit of this is that it can simplify the processing of parameters by dealing with one parameter at a time, which can also improve the flexibility and readability of the program. This also makes the program more manageable. Also dividing the code into smaller pieces would make it reuse-friendly.

    For example:

    function curryMinus(x) 
    {
      return function(y) 
      {
        return x - y;
      }
    }
    
    var minus5 = curryMinus(1);
    minus5(3);
    minus5(5);
    

    I can also do...

    var minus7 = curryMinus(7);
    minus7(3);
    minus7(5);
    

    This is very great for making complex code neat and handling of unsynchronized methods etc.

    0 讨论(0)
  • 2020-11-21 06:14

    It can be a way to use functions to make other functions.

    In javascript:

    let add = function(x){
      return function(y){ 
       return x + y
      };
    };
    

    Would allow us to call it like so:

    let addTen = add(10);
    

    When this runs the 10 is passed in as x;

    let add = function(10){
      return function(y){
        return 10 + y 
      };
    };
    

    which means we are returned this function:

    function(y) { return 10 + y };
    

    So when you call

     addTen();
    

    you are really calling:

     function(y) { return 10 + y };
    

    So if you do this:

     addTen(4)
    

    it's the same as:

    function(4) { return 10 + 4} // 14
    

    So our addTen() always adds ten to whatever we pass in. We can make similar functions in the same way:

    let addTwo = add(2)       // addTwo(); will add two to whatever you pass in
    let addSeventy = add(70)  // ... and so on...
    

    Now the obvious follow up question is why on earth would you ever want to do that? It turns what was an eager operation x + y into one that can be stepped through lazily, meaning we can do at least two things 1. cache expensive operations 2. achieve abstractions in the functional paradigm.

    Imagine our curried function looked like this:

    let doTheHardStuff = function(x) {
      let z = doSomethingComputationallyExpensive(x)
      return function (y){
        z + y
      }
    }
    

    We could call this function once, then pass around the result to be used in lots of places, meaning we only do the computationally expensive stuff once:

    let finishTheJob = doTheHardStuff(10)
    finishTheJob(20)
    finishTheJob(30)
    

    We can get abstractions in a similar way.

    0 讨论(0)
  • 2020-11-21 06:14

    If you understand partial you're halfway there. The idea of partial is to preapply arguments to a function and give back a new function that wants only the remaining arguments. When this new function is called it includes the preloaded arguments along with whatever arguments were supplied to it.

    In Clojure + is a function but to make things starkly clear:

    (defn add [a b] (+ a b))
    

    You may be aware that the inc function simply adds 1 to whatever number it's passed.

    (inc 7) # => 8
    

    Let's build it ourselves using partial:

    (def inc (partial add 1))
    

    Here we return another function that has 1 loaded into the first argument of add. As add takes two arguments the new inc function wants only the b argument -- not 2 arguments as before since 1 has already been partially applied. Thus partial is a tool from which to create new functions with default values presupplied. That is why in a functional language functions often order arguments from general to specific. This makes it easier to reuse such functions from which to construct other functions.

    Now imagine if the language were smart enough to understand introspectively that add wanted two arguments. When we passed it one argument, rather than balking, what if the function partially applied the argument we passed it on our behalf understanding that we probably meant to provide the other argument later? We could then define inc without explicitly using partial.

    (def inc (add 1)) #partial is implied
    

    This is the way some languages behave. It is exceptionally useful when one wishes to compose functions into larger transformations. This would lead one to transducers.

    0 讨论(0)
  • 2020-11-21 06:15

    Here is the example of generic and the shortest version for function currying with n no. of params.

    const add = a => b => b ? add(a + b) : a; 
    

    const add = a => b => b ? add(a + b) : a; 
    console.log(add(1)(2)(3)(4)());

    0 讨论(0)
  • 2020-11-21 06:16

    As all other answers currying helps to create partially applied functions. Javascript does not provide native support for automatic currying. So the examples provided above may not help in practical coding. There is some excellent example in livescript (Which essentially compiles to js) http://livescript.net/

    times = (x, y) --> x * y
    times 2, 3       #=> 6 (normal use works as expected)
    double = times 2
    double 5         #=> 10
    

    In above example when you have given less no of arguments livescript generates new curried function for you (double)

    0 讨论(0)
  • 2020-11-21 06:21

    In an algebra of functions, dealing with functions that take multiple arguments (or equivalent one argument that's an N-tuple) is somewhat inelegant -- but, as Moses Schönfinkel (and, independently, Haskell Curry) proved, it's not needed: all you need are functions that take one argument.

    So how do you deal with something you'd naturally express as, say, f(x,y)? Well, you take that as equivalent to f(x)(y) -- f(x), call it g, is a function, and you apply that function to y. In other words, you only have functions that take one argument -- but some of those functions return other functions (which ALSO take one argument;-).

    As usual, wikipedia has a nice summary entry about this, with many useful pointers (probably including ones regarding your favorite languages;-) as well as slightly more rigorous mathematical treatment.

    0 讨论(0)
提交回复
热议问题