Introduction to the

Where does corrification come from

The transliteration of Currying. Currying is a technique for implementing multi-parameter functions at the compiler level.

Before we talk about Currying in JavaScript, we can talk about what the original Currying is and where it came from.

In coding, what we code farmers are essentially doing is breaking down complex problems into small, programmable problems.

Currying provides a recursively degenerate way of implementing functions that take multiple arguments — transforming a function that takes a single argument (the first argument of the original function) and returning a new function that takes the remaining arguments and returns a result. In some programming languages (such as Haskell), Multi-parameter functions are supported by using Currying technology.

So, Currying was originally a compilation principle technology that implemented multi-parameter functions.

Where does corrification go

In Haskell, functions are first-class citizens, and Currying has become a language feature from a compilation principle technology. In terms of language features, what is a Currying?

In the Book Mostly Adequate Guide, it is summarized as Currying — passing a function only a few arguments to call it and having it return a function that handles the rest.

Therefore, the use of Currying is based on functional programming. After having Currying, we will explore its use and significance. And because of its usefulness and significance, it was actively extended to other programming languages.

Implement Currying in JavaScript

In order to implement the property described in this sentence, call a function by passing it only a few arguments and let it return a function to process the rest of the arguments. Let’s start by writing a function add that implements addition:

function add (x, y) {

  return (x + y)

}
Copy the code

This function is called curriedAdd, which can be used by rying rying. According to the definition above, curriedAdd must satisfy the following conditions:

curriedAdd(1) (3) = = =4

// true

var increment = curriedAdd(1)

increment(2) = = =3

// true

var addTen = curriedAdd(10)

addTen(2) = = =12

// true
Copy the code

CurriedAdd functions that satisfy the above conditions can be implemented with the following code snippet:

function curriedAdd (x) {

  return function(y) {

    return x + y

  }
}
Copy the code

Of course, there are some problems with this implementation: it’s not generic, and we don’t want to implement Currying by re-encoding the function itself.

However, this implementation of curriedAdd shows that one of the basics of implementing Currying — the ability to delay evaluation of Currying requires a scope in JavaScript — is that, in more general terms, we need to use a scope to store the last parameters passed in.

Abstract curriedAdd, and you might get the following function currying:


function currying (fn, ... args1) {

    return function (. args2) {

        returnfn(... args1, ... args2) } }var increment = currying(add, 1)

increment(2) = = =3

// true

var addTen = currying(add, 10)

addTen(2) = = =12

// true
Copy the code

In this implementation, the return value of a currying function is actually a function that takes the remaining arguments and immediately returns the calculated value. That is, its return value is not automatically curried. So we can use recursion to return a function that curries automatically.

function trueCurrying(fn, ... args) {

    if (args.length >= fn.length) {

        returnfn(... args) }return function (. args2) {

        returntrueCurrying(fn, ... args, ... args2) } }Copy the code

The above functions are very short, but they implement the core idea of Currying. The core idea of the Curry method is not very different. It compares the total number of arguments accepted multiple times with the number of arguments entered by a function definition, and returns the result when the number of arguments accepted is greater than or equal to the number of arguments passed by a Currying function. Otherwise returns a function that continues to accept arguments.

The section of code in Lodash that implements Currying is longer because it takes into account more things, such as binding the this variable, etc. Instead of Posting the code snippet from Lodash directly here, interested students can take a look at the Lodash source code and compare the difference between the two implementations.

However, the definition and implementation of Currying is not the most important thing. This article will focus on how it can solve coding and development problems, and how to choose the right type of Currying to solve different problems.

Use scenarios of Currying

Parameters of reuse

A fixed parameter that can reuse parameters is one of the main uses of Currying.

The above mentioned increment and addTen are examples of parameter reuse. After fixing the first parameter to 10 for the add method, the change method becomes a method that increments the value of the accepted variable by 10.

Delay the

Delayed execution is also an important use scenario for Currying, as can bind and arrow functions.

In front-end development, a common scenario is to bind an onClick event to a tag, while considering passing parameters to the bound method.

Here are some common ways to compare the pros and cons:

  1. Through the data attribute

    <div data-name="name" onClick={handleOnClick} />
    Copy the code

    Only string data can be passed via the data attribute nature. If complex objects need to be passed, only json.stringify (data) can be passed in JSON object format, but more complex objects are not supported. (Although there is no need to pass complex objects most of the time)

  2. Through bind

    <div onClick={handleOnClick.bind(null, data)} />
    Copy the code

    The bind method is very similar in functionality to the currying method implemented above, and is almost identical in implementation. Perhaps the only difference is that bind forces binding to the context, meaning that the first argument to bind is referred to as this when the original function is run. Currying does not require this parameter. So using currying or bind is just a matter of choice.

  3. Arrow function

    <div onClick={() => handleOnClick(data))} />
    Copy the code

    The arrow function allows for delayed execution and does not have to specify the context as the bind method does. Perhaps the only thing to worry about in React is that there will be objections to writing arrow functions inside the JSX tag, which will lead to writing business logic directly inside the JSX tag.

  4. By currying

    <div onClick={currying(handleOnClick, data)} />
    Copy the code

The performance comparison

Using jsPerf to test the performance of four methods, the result is: arrow function >bind>currying>trueCurrying.

Currying is similar to bind, but not as efficient because bind is implemented by browsers.

From this point of view, Currying performance is definitely the worst, but on the other hand, even the worst implementation of trueCurrying can reach 50W Ops/s on my PC, which means that these capabilities are nothing to worry about.

However, automatic Currying is realized in trueCurrying method, which is not available in the other three methods.

Do you need Currying

Why Currying

  1. In order to multiparameter function reusability

    What is really amazing about Currying is that functions can be reused in this way.

    Convert the add function to increment, addTen, and so on with one line of code.

    Placeholder magic operations for a complex implementation of Currying, with Lodash as a column. Play with the reuse of multi-parameter functions.

    import _ from 'loadsh'
    
    function abc (a, b, c) {
      return [a, b, c];
    }
    
    var curried = _.curry(abc)
    
    // Curried with placeholders.
    curried(1) (_,3) (2)
    // => [1, 2, 3]
    Copy the code
  2. Designed for functional programming

    Currying is something that comes with functions. There should be a whole suite of functional programming things, pure functions, compose, Containers, and so on. (Read Along-adequate – Guide)

    If you want to write Pointfree javascript-style code, Currying is essential.

    To use compose, to use containers, etc., we also need Currying.

Why not Currying

  1. Some of the features of Currying have other solutions

    If we just want to bind parameters ahead of time, there are several readily available options, such as bind, arrow functions, and more, with better performance than Curring.

  2. Currying is stuck in functional programming

    In this article, there is an implementation of trueCurrying that best meets the definition of Currying. It also provides “novel” features that are not available, such as bind, arrow functions, etc. — sustainable Currying (a term I coined).

    But this “novelty” feature is not as widely used as might be expected.

    The reason is that Currying is a product of, born of, and used by, functional programming.

    JavaScript, on the other hand, is not really a functional programming language. JavaScript uses functional features such as Currying, which have additional performance overhead and lack type derivation compared to functional programming languages such as Haskell.

    As a result, there are few projects that write JavaScript code that conforms to functional programming ideas and specifications, thus limiting the common use of technologies like Currying in JavaScript code.

    If we are not ready to write functional programming specification code, we only need to bind parameters in JSX code once in advance, then the bind or arrow functions are sufficient.

conclusion

  1. Currying is “low performance” in JavaScript, but these capabilities are negligible in most scenarios.
  2. The idea of Currying can greatly improve the reusability of functions.
  3. Currying came from and fell into functional programming. If you are not ready to write pure functional code, there is a better alternative to Currying.
  4. Functional programming and its ideas are worth paying attention to, learning and applying. So at the end of this article, again, amway JavaScript programmers should read this book — The Carrier-Adequate Guide

Refer to the link

  • Corrification – Wikipedia
  • JS Functional Programming Guide
  • Pointfree Programming Style Guide by Yifeng Ruan