Functional-Light JavaScript, v3

Partial Application & Currying

Kyle Simpson

Kyle Simpson

You Don't Know JS
Functional-Light JavaScript, v3

Check out a free preview of the full Functional-Light JavaScript, v3 course

The "Partial Application & Currying" Lesson is part of the full, Functional-Light JavaScript, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle introduces two techniques for specializing functions, partial application, where inputs are preset in a series of calls to utilities, and currying, where a function is called with an input a specified number of times.


Transcript from the "Partial Application & Currying" Lesson

>> Kyle Simpson: In terms of our AJAX function, there are two techniques for how we could specialize it. One of those techniques is called partial application, so let's look at partial application. Here's my AJAX function, line 1. Line 3, I am making a partial application of the AJAX function, and that result is getCustomer.

And the way that I have made getCustomer out of AJAX, is by pre-specifying the customer API URL as its first input. So envision a utility called partial, which I'm not gonna show the implementation of because it doesn't really matter how its implemented, but it's provided to you by all the functional libraries.

It takes a function is its first input, and then it takes as its next inputs a set of arguments to pass along to that function at some point. So it's like pre setting those arguments, and we get back a new function called getCustomer. I can take line 4, another parcel of AJAX and provide it to inputs, and get me a getCurrentUser.

But line 5 is better than line 4, for the exact same reason is we just talked about. Line 5 makes a more clear delineation of the relationship between getCurrentUser and getCustomer. That is getCurrentUser is a partial application of getCustomer.
>> Kyle Simpson: So though that partial utility allows me each time I call it to preset one or more inputs, and produce a function which is expecting all the rest of the inputs.

That's what partial application is.
>> Kyle Simpson: Partially applying some of the inputs now, receiving all of the inputs later. You'll notice that to do a two-stage specialization like I did, I had to call partial twice. Do you see that? I had to call partial once, and then I called it the second time to make the getCurrentUser.

>> Kyle Simpson: That's one way of doing specialization, it's called partial application. Another way which quite frankly is much more common within programme functioning. You will tend to want to do partial application as you get started, and then you'll find out actually everybody does currying, okay? And you'll see why as you go along, as we go along in the course and as you get more practice with this, but currying is the much more common form of specialization.

I used to tell people and many people have said this before, I used to tell people that currying was a special form of partial application. I now would describe them more like cousins. They both accomplish the same end goal, they both specialize a generalized function, but they go about it in a somewhat significantly different way.

So let's look at currying. Back to our AJAX function, what if I wrote the AJAX function like this, okay? It looks a little bit different because I have this three levels here. I have an AJAX level, and then a getData level, and then a getCallback level, so I've got three levels of function going on.

And notice line 7 when I call it, I'm doing a first set of parentheses line 7 for the CUSTOMER_API, that provides the URL. And I get back another function which is expecting the next input. And then I get back another function which is expecting the next input. You see where I'm going here?

So I've got three functions nested, and then I've got three function calls. That's what I would sort of refer to as a manual currying, okay? And you'll sometimes see people define, if they just have a two or maybe a three level currying, you'll see them list out the functions nested like that.

On the next slide we'll see an alternate way of writing out a manual curry. But that allows me then to call those functions and save off the intermediate function. That's how we get the specialization. If I call AJAX with only CUSTOMER_API, I get back a function which could be called getCustomer.

The function on line 2 is essentially getCustomer. Use your equational reasoning and you'll see they're basically the same thing. And then if I call the getCustomer with the data, what I get back is getCurrentUser. So, you'll see the same specialization just as we're doing on the previous slide, but now notice that I didn't have to call a utility every line.

All I had to do to get the more specialized function, was just parse in the next input. Parse in an input, get a more specialized function. Parse in another input, get an even more specialized function. And you keep doing that, you keep getting a more specialized function every time.

>> Kyle Simpson: This is a technique called currying. Where does that come from by the way? The Haskell programming language, everybody knows or probably has heard at some point or another about Haskell. I don't really know anything at all about Haskell. I can literally write one line of Haskell, that's all I know about the programming language Haskell.

But what I know is that one of the co-inventors of Haskell, his name was Haskell Curry. He invented this technique of currying, or at least co-invented this technique of currying. We call it currying because it is essentially the way that all inputs go into functions in Haskell. So in Haskell you don't write like a binary or an unary function, there is no such thing.

All functions are unary in Haskell. So, if you wanna pass in three inputs, what do you do? You have a curried function that takes them one at a time. There's no such thing as parse in all three all at once kind of thing. So, currying comes from this idea of, if I could only parse in in one input at a time, how could I make multiple inputs go into a function?

Sometimes my function needs multiple inputs. Now, this is doing it manually, but it would be nice if, for example, we had a utility that could do that for us. And indeed, we do have a utility that can do that for us. By the way in the comments in lines, you will notice that I'm reusing the arrow function syntax.

Line 1 is the traditional way that is written out, and that you will see a URL and then the fat URL. Let me highlight this for you, you'll see URL here.
>> Kyle Simpson: My highlighter will ever work, there we go. URL, and then the arrow, and then data, and then an arrow, and then cb, and then an arrow, and then whatever the function needs to do to do its work, okay?

That's that three level nesting, it's just written all in one line. And a lot of functional programmers really like the arrow function syntax, because this arrow function syntax is almost identical to the mathematical notation and the Haskell notation for a curried function. That's why they love writing it in that style.

I am decidedly not a fan of aero function syntax, which is why you haven't seen any arrow functions on any of my slides. I'm not a fan of that syntax, but if you absolutely must do this chained arrow currying thing, please do line 2. Do a favor to the reader and at least wrap parentheses around each function boundary.

Just slightly more not so crazy on the readability, okay? If I can't convince you not to do nested arrow functions, please at least wrap your arrow functions in parentheses, your nested arrow functions in parentheses. Okay, arrow functions aside, in Javascript we can define a utility, and indeed all functional libraries will provide you a utility.

It's often called curry, sometimes they'll have a variation of it called curry n, meaning how many I wanna curry. It looks like this. You call curry, you tell it how many inputs you're expecting to receive, and then you provided a function. And notice that this function here doesn't have to be manually curried, it's a regular old normal function that's expecting some n number of inputs.

This curry utility automatically adapts it into being that unrolled thing that's going to accept one input at a time.
>> Kyle Simpson: In other words, it creates a wrapper adapted function, whose job is to keep returning a new function that expects another input, until you've provided the specified number of inputs.

And then it calls the underlying function with all those collected inputs. And that gives us the ability in line 7 to call AJAX with the URL, and get back a getCustomer function. And then call getCustomer with a data object, and get back or getCurrentUser function.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now