JavaScript
Article

A Beginner’s Guide to Currying in Functional JavaScript

By M. David Green

An Introduction To Functional Javascript

Currying, or partial application, is one of the functional techniques that can sound confusing to people familiar with more traditional ways of writing JavaScript. But when applied properly, it can actually make your functional JavaScript more readable.

More Readable And More Flexible

One of the advantages touted for functional JavaScript is shorter, tighter code that gets right to the point in the fewest lines possible, and with less repetition. Sometimes this can come at the expense of readability; until you’re familiar with the way the functional programming works, code written in this way can be harder to read and understand.

If you’ve come across the term currying before, but never knew what it meant, you can be forgiven for thinking of it as some exotic, spicy technique that you didn’t need to bother about. But currying is actually a very simple concept, and it addresses some familiar problems when dealing with function arguments, while opening up a range of flexible options for the developer.

What Is Currying?

Briefly, currying is a way of constructing functions that allows partial application of a function’s arguments. What this means is that you can pass all of the arguments a function is expecting and get the result, or pass a subset of those arguments and get a function back that’s waiting for the rest of the arguments. It really is that simple.

Currying is elemental in languages such as Haskell and Scala, which are built around functional concepts. JavaScript has functional capabilities, but currying isn’t built in by default (at least not in current versions of the language). But we already know some functional tricks, and we can make currying work for us in JavaScript, too.

To give you a sense of how this could work, let’s create our first curried function in JavaScript, using familiar syntax to build up the currying functionality that we want. As an example, let’s imagine a function that greets somebody by name. We all know how to create a simple greet function that takes a name and a greeting, and logs the greeting with the name to the console:

var greet = function(greeting, name) {
  console.log(greeting + ", " + name);
};
greet("Hello", "Heidi"); //"Hello, Heidi"

This function requires both the name and the greeting to be passed as arguments in order to work properly. But we could rewrite this function using simple nested currying, so that the basic function only requires a greeting, and it returns another function that takes the name of the person we want to greet.

Our First Curry

var greetCurried = function(greeting) {
  return function(name) {
    console.log(greeting + ", " + name);
  };
};

This tiny adjustment to the way we wrote the function lets us create a new function for any type of greeting, and pass that new function the name of the person that we want to greet:

var greetHello = greetCurried("Hello");
greetHello("Heidi"); //"Hello, Heidi"
greetHello("Eddie"); //"Hello, Eddie"

We can also call the original curried function directly, just by passing each of the parameters in a separate set of parentheses, one right after the other:

greetCurried("Hi there")("Howard"); //"Hi there, Howard"

Why not try this out in your browser?

JS Bin on jsbin.com

Curry All the Things!

The cool thing is, now that we have learned how to modify our traditional function to use this approach for dealing with arguments, we can do this with as many arguments as we want:

var greetDeeplyCurried = function(greeting) {
  return function(separator) {
    return function(emphasis) {
      return function(name) {
        console.log(greeting + separator + name + emphasis);
      };
    };
  };
};

We have the same flexibility with four arguments as we have with two. No matter how far the nesting goes, we can create new custom functions to greet as many people as we choose in as many ways as suits our purposes:

var greetAwkwardly = greetDeeplyCurried("Hello")("...")("?");
greetAwkwardly("Heidi"); //"Hello...Heidi?"
greetAwkwardly("Eddie"); //"Hello...Eddie?"

What’s more, we can pass as many parameters as we like when creating custom variations on our original curried function, creating new functions that are able to take the appropriate number of additional parameters, each passed separately in its own set of parentheses:

var sayHello = greetDeeplyCurried("Hello")(", ");
sayHello(".")("Heidi"); //"Hello, Heidi."
sayHello(".")("Eddie"); //"Hello, Eddie."

And we can define subordinate variations just as easily:

var askHello = sayHello("?");
askHello("Heidi"); //"Hello, Heidi?"
askHello("Eddie"); //"Hello, Eddie?"

JS Bin on jsbin.com

Currying Traditional Functions

You can see how powerful this approach is, especially if you need to create a lot of very detailed custom functions. The only problem is the syntax. As you build these curried functions up, you need to keep nesting returned functions, and call them with new functions that require multiple sets of parentheses, each containing its own isolated argument. It can get messy.

To address that problem, one approach is to create a quick and dirty currying function that will take the name of an existing function that was written without all the nested returns. A currying function would need to pull out the list of arguments for that function, and use those to return a curried version of the original function:

var curryIt = function(uncurried) {
  var parameters = Array.prototype.slice.call(arguments, 1);
  return function() {
    return uncurried.apply(this, parameters.concat(
      Array.prototype.slice.call(arguments, 0)
    ));
  };
};

To use this, we pass it the name of a function that takes any number of arguments, along with as many of the arguments as we want to pre-populate. What we get back is a function that’s waiting for the remaining arguments:

var greeter = function(greeting, separator, emphasis, name) {
  console.log(greeting + separator + name + emphasis);
};
var greetHello = curryIt(greeter, "Hello", ", ", ".");
greetHello("Heidi"); //"Hello, Heidi."
greetHello("Eddie"); //"Hello, Eddie."

And just as before, we’re not limited in terms of the number of arguments we want to use when building derivative functions from our curried original function:

var greetGoodbye = curryIt(greeter, "Goodbye", ", ");
greetGoodbye(".", "Joe"); //"Goodbye, Joe."

JS Bin on jsbin.com

Getting Serious about Currying

Our little currying function may not handle all of the edge cases, such as missing or optional parameters, but it does a reasonable job as long as we stay strict about the syntax for passing arguments.

Some functional JavaScript libraries such as Ramda have more flexible currying functions that can break out the parameters required for a function, and allow you to pass them individually or in groups to create custom curried variations. If you want to use currying extensively, this is probably the way to go.

Regardless of how you choose to add currying to your programming, whether you just want to use nested parentheses or you prefer to include a more robust carrying function, coming up with a consistent naming convention for your curried functions will help make your code more readable. Each derived variation of a function should have a name that makes it clear how it behaves, and what arguments it’s expecting.

Argument Order

One thing that’s important to keep in mind when currying is the order of the arguments. Using the approach we’ve described, you obviously want the argument that you’re most likely to replace from one variation to the next to be the last argument passed to the original function.

Thinking ahead about argument order will make it easier to plan for currying, and apply it to your work. And considering the order of your arguments in terms of least to most likely to change is not a bad habit to get into anyway when designing functions.

Conclusion

Currying is an incredibly useful technique from functional JavaScript. It allows you to generate a library of small, easily configured functions that behave consistently, are quick to use, and that can be understood when reading your code. Adding currying to your coding practice will encourage the use of partially applied functions throughout your code, avoiding a lot of potential repetition, and may help get you into better habits about naming and dealing with function arguments.

If you enjoyed, this post, you might also like some of the others from the series:

  • http://careersreport.com frances.jenkins4

    Here is something really worth your attention , a very good opportunity for work for those who want to utilise their free time to make some extra money using their computers… I have been working on this for last two and half years and I am earning 50-80 dollar/ hour … In the past week I have earned 13,245 dollars for almost 20 hours sitting ….

    There are no special skills required just basic typing and an internet connection ….

    There are no time constraints … You may do this any time when you are free ….

    check it what I’ve been doing….Visit websiteIink on my profiIe` to see what I do`

    #d5

  • https://www.phpcontext.com/wordpress Mike Mx

    Any practical usage examples?

    • http://Post20.com robert_joseph2

      Here is something extremely interesting that is worth to pay attention , a superb opportunity for work for those who want to utilise their free time to make some extra money using their computers… I have been working on this for last two and half years and I am earning 50-80 dollar/ hour … In the past week I have earned 13,245 dollars for almost 20 hours sitting ….

      Any special kind of skills or qualification is not required for this, just normal typing and a reliable internet connection ….

      Time limitations are not here to start work … You may work on this any time when you get some time ….

      Check it out how I’ve been doing this….view WebsiteIink on my` profile` to know how I use to work on this`

      &5g

    • http://Post20.com Deborah Boyer

      This is something very interesting that is worth paying your extreme attention ,a very good chance to work for those people who want to use their free time so that they can make some extra money using their computers… I have been working on this for last two and half years and I am earning 60-90 dollar/ hour … In the past week I have earned 13,70 dollars for almost 20 hours sitting ….

      Any special qualification, degree or skills is not necessary for this, just keyboard typing and a good working and reliable internet connection ….

      Not any Time limitations to start work … You may do this work at any time when you willing to do it ….

      Just know how I have been doing this…..….see this (webiste-Iink) on my !profile!` to know how I am working` on this`

      #34FGT

    • Jacob Groß

      Same question here. As I’ve never written Haskell and such I have no idea why I should use this.

    • http://codingtales.com/ Abdulsattar Mohammed

      It goes really well with other functional programming features. For example, if you use compose, you can write `compose(sum, curryMap(square))([1..100])` if sum and square are functions.

    • http://kongware.net/blog Iven Marquardt

      Currying reveals its benefits only in combination with another, more advanced functional feature: combinatorics. Function composition for example, is based on the compose function which is also known as the k-combinator. There are many others. When you start functional programming, currying is going to become the most natural matter for you.

  • http://lasvegasurgentcare.com/ Super Vegas

    This is great thank you.

  • http://xabikos.com/ xaralabos karypidis

    Great explanation right in point! Thanks for writing this.

  • PVgr

    Good explanation, and the article is easy to follow, but I still don’t get the why. I mean, what is a real-world problem that can be solved better with currying. Thanks!

    • josh

      As I understand it, any time you find yourself passing the same parameter value lots of times could be curried so that isn’t happening:

      callFunc(123, ‘xyz’)

      callFunc(123, ‘abc’)

      callFunc(123, ‘def’)

      vs

      callFuncCurried123(‘xyz’)

      callFuncCurried123(‘abc’)

      callFuncCurried123(‘def’)

      • PVgr

        Thank you!

      • c3p0

        In this case couldn’t you just pass in an array to callFunc() like:

        var myArr = [123, ‘xyz’];
        callFunc(myArr);

        Still trying to wrap my head around when / how I should use this. Thanks!

  • http://thejsguy.com/ David Tang

    So what is the difference between currying and partial application? Can those words be used interchangeably?

    • Slava Ganzin

      curry is partial application with 1 arity in math.
      But in js everyone just don’t give a fuck and mix them.

      • http://thejsguy.com/ David Tang

        and 1 arity means?

        • Slava Ganzin

          arity mean number of arguments of a function

  • Qbe Root

    No mention of Function.prototype.bind? :-( Aside from locking the this value, it allows partial application of functions, like currying. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Partial_Functions

    • mdavidgreen

      Function.prototype.bind can be used to curry, but it’s usually more verbose than using a specialized curry function, and may make your intention less clear to someone reading the code who’s familiar with how bind is usually used.

  • RentBin.com

    Wow, great explanation!!!

  • Ryan Tomczik

    My implementation of the Curry function in ES6

    const curry = fun => […Array(fun.length-1)].reduce((acc, _) => (…args) => (…args2) => acc(…args, …args2), fun);

  • Huitre

    The best practical example is event listener or middleware. It often happens that you need to add extra parameters to the callback. Well, currying solve this problem.

    const a = 42;
    Button.onClick = dummy(a);
    dummy(a) { return function(evt) { console.log(a, evt) } }

    Great post btw !

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.