The original article with code snippet images is available here -> https://easyontheweb.com/currying-vs-partial-application-in-javascript/
If you have ever delved into functional programming like me you know how important the concepts of currying and partial application are in functional programming. Even though these are kind of similar topics they are not exactly the same. So, in this article we’ll explore both of these and also see how they are currying and partial application differ using Javascript as our language of choice.
Currying is a very important concept in Javascript in general as well but is often studied just for the sake of clearing interviews rather than implementing it in your day to day job. We will also dive a little deep and check out how it can be a really powerful technique for you to write cleaner code.
Partial Application
We start with partial application because what I feel is that currying is more or less just a derivative of partial application and if you understand this well enough, you won’t have a difficult time in understanding currying as well.
Think of partial application as such – for functions with multiple arguments, partial application is a technique that allows us to specify some of the arguments up front and some arguments later !
partial application example
Just look at the piece of code above. This is an example of partial application. Let’s try to break it down line by line.
In the first line, we have defined a function called adder that just takes 3 arguments and well, as the name suggests, returns the addition of all three of them.
We store the result of adding 2,3 and 5 in a variable called result that we’ll take a look at later in the code.
The next line is where we are using partial application. Remember what I said, partial application means to specify certain arguments up front and certain arguments later. addToN is a function that is taking one argument called n and returns a function that takes two arguments num2 and num3. This function that addToN is returning when called actually inside it calls the adder function that we declared above with arguments as n, num2 and num3.
Think of this single line of code in many steps – the first step is writing a function that takes one argument ‘n’, the next step is that this function that we wrote is a higher order function which itself is returning another function. Cool ? The function that gets returned itself takes two arguments ‘num2’ and ‘num3’. In the next step, that is whenever this function gets called we call the adder function with all the three arguments we have taken so far in two different functions.
I specifically re-wrote the same thing in two paragraphs so as to explain how this is working one by one.
In the next line, we declared addTo5 as addToN(5). Just take a moment and think about what gets stored in addTo5. addTo5 is actually a function which will take two arguments, right? Because that is what addToN returns!
In the line after that we create a new variable called res which stores addTo5(3,10). Remember, addTo5 was a function that was supposed to get two arguments – that is what we have done here. Therefore, res is the output of what addTo5 returns which is nothing but the adder function being called upon 5,3,10 ,i.e, 18.
This happens due to a very important concept called closure that we will touch upon later. But I suppose you do get the concept behind how we broke a function with more arity (expected number of arguments) down to partial application and took 5 as an argument upfront and then passed 3 and 10 as the other arguments.
Currying
Now that we have discussed partial applications, let us go onto currying – currying can be thought of as a special case of partial applications where a function that expects multiple arguments is broken down into successive chained functions that each takes a single argument and returns a function that accepts the next argument.
currying example in javascript
This piece of code does not differ much from that of partial application in the sense that it also does the same underlying job of breaking a function with higher arity into smaller ones, the only difference being that here the number of arguments passed in is one at every step.
Here, addTo is a custom made curried function that can only curry for the adder function. Actually, functional programming libraries like Ramda and lodash will give you a general curry method that would allow you to curry any function but more on that later.
Please notice the line where the addTo function is being called. Actually, three different functions are being called there, all of them chained to one another and taking in a single argument. Note that in partial application, we gave one argument first and then two arguments together. That is the key difference here – all the arguments are going in one by one in currying.
Currying vs partial application
Generally speaking, both partial application and currying are mostly used when the arguments themselves are functions but I chose simpler examples so as to make you understand the underlying philosophy behind these concepts. As a small example, let us check this out :-
currying example 2
In this example I’m using a popular functional programming library called Ramda which gives us a very useful and generalised curry function. What this function expects is a function as the first argument and the no. of arguments it should wait for before executing that function as the second argument.
See how we created the function curriedAdd and we are giving it the two arguments as add (a function) and 3 (no. of arguments to wait for before executing the add on them). That. is why in the next line we could use the curried version to calculate res like curriedAdd(3)(4)(5).
Can you think what would be curriedAdd(3)(4) ? It would be a function that is waiting for one more argument and when it gets that argument it would run the add function .
I will leave figuring out the working of the rest of code with the map function to you. Please comment if you need explanation on that. But I would recommend trying to run it and understanding how it is working first.
As for the difference part between currying and partial application, I’ve already told it many times in this article – it is just about the no. of arguments we present upfront.
Role of closure in currying and partial application
I’ll not be going deep into closures here as that is a super huge and important concept in Javascript in general and I really hope you do know what it is. If not, a google search will bring up a plethora of good resources.
How closure is key in concepts like currying and partial application is that closure helps in remembering the older values, ie, the arguments that were given upfront. Let us think about partial application here, we give say ‘x’ arguments now and then ‘y’ arguments later. When we give the ‘x’ arguments to a function working on partial application, what it does is form a closure around the ‘x’ values and returns a function from inside it. Therefore, these x values are available to the function that is returned to be used later (and that is what it actually does!).
Due to closure, the values of the earlier arguments is remembered and then the final function call is able to use those values as well.
Advantages of currying and partial application
When we don’t know all the arguments for a function at the same time.
Composition of functions is much easier with just one argument therefore currying is widely used in functional programming.
Creating specialised functions out of more general functions with higher arity is useful in separation of concerns.
There are numerous other advantages of currying and partial application and if you are interested in functional programming and all you’ll appreciate these two concepts even more. Even if you are not, they are powerful techniques that can help you write cleaner and more robust code.
Are you interested in learning about passing by value and passing by reference in Javascript then please check this article out -> https://easyontheweb.com/passing-by-value-vs-passing-by-reference-in-javascript/
Top comments (0)