Comments

Functional Programming Demystified: Currying Vs Partial Application

Most JavaScript developers don’t understand Currying & Partial Application. But written much JavaScript chances are good you’ve reaped the benefits of these concepts. It’s worth taking the time to figure out what is actually going on underneath the hood.

The concepts I cover in this article will come up in interviews, JavaScript Promises, libraries like Redux, and so much more.

But let’s face it – functional programming can be confusing. A lot of talks around functional programming that I’ve seen have people using words like “arity” and providing code examples in Haskell.

note: arity just means “The number of parameters a function takes”. A function that takes 2 parameters has an arity of 2.

This article will have as little of that as possible. All code examples will be written in JS.

That said these are tough topics to understand. I highly recommend playing around with the code snippets I provide in this article and taking the time to understand this stuff for yourself.

“What I cannot create, I do not understand.” – Richard Feynman

What is Currying?

Currying is the process of taking in a function that accepts multiple parameters as input and returning a function that accepts a single argument.

This might sound simple, but it’s actually a pretty advanced concept. Let’s see how it looks in practice:

function add4(a,b,c,d) {
    return a + b + c + d;
}

const add = curry(add4)
const result = add(1)(2)(3)(4);
console.log(result) // 10

Pretty simple overall – but line 6 has a tendency to trip people up sometimes.

What’s happening is that each time the curried function is called, it returns a brand new function. This function binds the previous arguments to the curried function. When all of the arguments have been passed to the underlying function, the result is returned.

A lot of people like to describe this as “built-in iterator behavior”.

Why Curry?

Hopefully, you’re starting to understand what currying is and how it works. But why would you actually want to use this strange syntax?

Currying gives you the ability to wrap any function with a well-defined container. A real example of this is promises. Promises wrap the asynchronous parts of your program with a well-defined container object. This abstracts having to deal with the internals of asynchronous programming, and instead you just call “.then()” when you want to proceed to the next step.

Currying is also useful for:

  • Allowing you to bind pieces of data to a function in various places, one at a time. This is especially useful if you are passing a function around different parts of your application
  • Making event handling work! Check out this blog post for an excellent deep dive.
  • Creating more reusable functions since you can guarantee that the function takes exactly one parameter as input

What is Partial Application?

Partial application is a more generalized version of currying. It is any function that takes a function with multiple parameters and returns one with fewer parameters.

Here’s a basic example:

function add4(a,b,c,d) {
    return a + b + c + d;
}

function partialApply(func, a, b) {
     return function(c,d) {
        func(a,b,c,d);
     }
}

const add2 = partialApply(add4, 1, 2)
add2(3,4) // 10

It’s important to note that the partialApply function I wrote here is not generalized. It will only work to transform a function that takes 4 parameters into a function that takes 2 parameters.

With that disclaimer – let’s take a look at what’s going on. partialApply takes in a function and 2 additional parameters. It then creates and returns a new function that takes 2 arguments, and appends them to the parameters that were already passed in.

This works because of JavaScript scope and closure. If you don’t already understand this topic, go read about it right now. We’re hoping to publish an article all about scope in the near future – but for now, Google is your friend.

Okay – sorry for that detour. As you can see from the example, partial application works almost exactly the same way as currying. It takes a function and some arguments and returns a new function with those arguments applied to the original function.

If you’ve ever called .bind in JavaScript, you are using partial application! A classic use case in React is binding a callback function to “this”.

class Example extends React.Component {
    constructor() {
        this.onClick = this.onClick.bind(this);
    }

    onClick(e) {
        this.setState({
            'clicked': true,
        });
    }

    render() {
        return <button onClick={this.onClick}>Click me!</button>
    }
}

Luckily – there are better ways to do this in React nowadays, but the concept still applies. Partial application provides many of the same benefits as currying. Sometimes it is essential to getting your code to work! If you’ve ever run into bugs where you get the error message: ‘this’ is not defined – there’s a good chance you need to reach for partial application.

A Real World Example

I’ve talked abstractly about when these concepts *might* be useful and explained why they are helpful, but let’s work through a simple real-world example so you can start using this stuff right away!

function getProbability(totalWeight, itemWeight) {
  return itemWeight/totalWeight;
}

items = [1,2,9,3,6,5,3]
total = 29

getProbabilityWithTotalApplied = (itemWeight) => {
  return getProbability(total, itemWeight);
}

items.map(getProbabilityWithTotalApplied)

In this case, we have a list of items where each element can be considered a “weight”. We want to map each item to a probability which will be calculated using the formula itemWeight/totalWeight.

Now there’s a number of ways that we could implement this. We could hard code the totalWeight variable inside of our getProbability function. We could also create an anonymous function inside of items.map to ensure that total, as well as itemWeight, are passed correctly.

But I think the cleanest approach is the one I show here, which utilizes partial application. This approach allows us to bind the total variable to the function before calling items.map, and thus we don’t need to pass in the totalWeight everywhere. This also has the advantage of letting us keep getProbability as generic as possible. We can always bind variables to this generic function at any point during runtime. Pretty cool!

Look for opportunities to play with this in your next project. I think you’ll be pleasantly surprised 😃.

Implementing .bind

In the last section, we worked through a simple example of how partial application could be implemented and applied.

In this section, we’ll peel back the layers a bit more to implement our own version of JavaScript’s .bind method.

The first step is understanding what bind is supposed to do.

From the Mozilla Developer Docs:

Syntax

function.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg

The value to be passed as the this parameter to the target function when the bound function is called. The value is ignored if the bound function is constructed using the new operator. When using bind to create a function(supplied as a callback) inside a setTimeout, any primitive value passed as thisArg is converted to object. If no arguments are provided to bind, the this of the executing scope is treated as the thisArg for the new function.

arg1, arg2, …

The value to be passed as the this parameter to the target function when the bound function is called. The value is ignored if the bound function is constructed using the new operator. When using bind to create a function (supplied as a callback) inside a setTimeout, any primitive value passed as thisArg is converted to object. If no arguments are provided to bind, the this of the executing scope is treated as the thisArg for the new function.

.bind is JavaScript’s way of allowing you to easily do partial application!

Here’s one more example to play around with:

function add3(a,b,c) {
    return a + b + c;
}

const add2 = add3.bind(this, 100);
console.log(add2(1, 1)); // 102

Now to implement our own .bind method, we also need our own .apply method. You might be thinking: “Jeez this sounds like a lot of work, now I have to implement 2 methods instead of the 1 that you promised”. You’re right – it is a lot of work. But trust me, once we get through apply, adding bind is only a few lines!

So let’s refresh our memory on .apply (again from Mozilla Developer Docs):

Syntax

function.apply(thisArg, [argsArray])

thisArg

The value of this provided for the call to func. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed. This argument is not optional

arg1, arg2, …

Optional. An array-like object, specifying the arguments with which func should be called, or null or undefined if no arguments should be provided to the function. Starting with ECMAScript 5 these arguments can be a generic array-like object instead of an array. See below for browser compatibility information.

And a quick example:

function hello(name) {
    console.log(`Hello ${name}`);
}

hello.apply(thhis, ["Taylor"]);
// "Hello Taylor" is logged

The real reason that implementing our own bind method is hard – and the reason we need .apply is the thisArg object. Being able to call any function from a specific context is a bit tricky. So if you don’t fully understand this part – don’t sweat it. It has very little to do with currying and partial application.

If you have the time, I highly recommend playing around with this repl.it to better understand how it works.

Here’s the code:

Function.prototype.myApply = function(thisArg, arr) {
    thisArg = thisArg || global;
    const uid = Math.random();
    thisArg[uid] = this;
    if (!arr) {
        res = thisArg[uid]();
    } else {
        res = thisArg[uid](...arr);
    }
    delete thisArg[uid]
    return res;
}

I have to admit – this is some weird code. We are creating a new property on the thisArg object that maps to the function we want to call. We generate a random number when creating this new property to avoid accidentally overriding an existing property on the thisArg object.

If you’re confused at this point – that’s totally normal. You can either accept that this code works and move on to the bind implementation or take some time to play with the code!

.Bind Code

Finally, we are ready to implement the bind method. The hard work has been done. Basically, all we need to do is create a function that wraps a call to .apply in a brand new function.

Here’s what it looks like:

Function.prototype.myBind = function(thisArg, ...args) {
    return function(...remainingArgs) {
        this.myApply(thisArg, [...args, ...remainingArgs])
    }
}

All the spread operators make it a little tricky to understand but it’s actually incredibly simple! We use scope/closure to return a new function that binds the list of arguments passed in – to the function that is calling the bind method. Remember that “this” refers to the function that called .bind in this context.

Even if you didn’t understand the last example, you should be able to understand what’s going on here.

Summary

  • Currying is the process of transforming a function with many parameters to a function with a single parameter
  • Partial application is transforming a function with multiple parameters to one with fewer parameters
  • These techniques are used in promises, event handling, and many of JavaScript’s built-in methods
  • Implementing your own .bind method is not that hard! It’s even easier if you cheat and use JavaScript’s build in .apply method 😊

If you enjoyed this article – and want to keep leveling up your JavaScript skills, I recommend checking out Mosh’s full-stack developer bundle.

As always, if you liked this article leave a comment down below and consider sharing with a friend! It really does help us out.

Hi, I’m Taylor. I’m a software engineer at Thumbtack. I care about helping others learn to code so they can find a job they love which is why I love working with Code With Mosh. I also write about life @ https://taylormilliman.me.
Tags: , , , , , , , , , ,

Leave a Reply

Connect with Me
  • Categories
  • Popular Posts