If you’ve been following this series from the beginning then I’m confident to say that by finishing this chapter we will have a solid understanding of the basics of functional programming.
So far we’ve covered the concepts of purity and immutability and ventured deeper into the world of functions by exploring composition and currying. In this article we will look into partial application, what it is and how to use it.
In order to produce more reusable functions and create better abstractions we need a mechanism to preset some of the arguments of a function.
Partial application is a technique used to transform functions of higher arity (functions that take multiple arguments) into multiple functions that take less arguments.
A partially applied function is a function that is not called with all of its arguments. Since it can’t execute anything yet it will return us another function that expects the rest. When we call the returned function with the remaining arguments it will run.
With this technique we try to achieve better reusability and abstraction. Often functions that get called with repeating arguments can be partially applied, thus hiding some of the implementation details of the function.
Both currying and partial application are techniques aiming to achieve the same goal — transform functions with many arguments into functions that take less arguments.
Even though they are similar in that, the way that they achieve it is different.
A curried function will be split into many chained functions all taking exactly one argument. This makes curried functions a lot more predictable — you always know what to expect.
A partially applied function, on the other side, does not have that limitation. You can apply it with any number of arguments and depending on that the returned function will have different arity. We only know that the returned function will take less arguments than the original.
There two techniques represent the same general concept but differ in the way we apply them. This is the reason they are often confused.
bind()
The simplest way to do partial application is using the built in method Function.prototype.bind
.
The most often use case for the bind
function is to create a new function with a preset this
value. We can also pass any amount of arguments that are going to be preset on the returned function.
In this case we don’t pass any value for the this
object but we pass two additional arguments who will be used as x
and y
. Then we take the partially applied function and call it with the last remaining argument z
.
To be fair, this isn’t an approach that I’ve ever used when working with teams. Not everyone is aware of that behaviour and using a function called partial
` or something in those lines would be at least a little bit more descriptive.
A situation in which I’ve found partial application to be particularly useful is when you want to apply default parameters.
There are times when we call a function with the same argument again and again. This could be an url for some API or a configuration object.
By using partial application we can supply the function with the repetitive parameters in advance and use it only to take the payload that we’re sending.
Sometimes we need to write complex functions that take many arguments. Generally I try to keep the amount of arguments that are passed to a maximum of three or four but there are cases in which things escalate and you end up with a giant function that takes seven arguments.
A function like that can easily get out of hand and force you to look up its definition every time you need to call it.
The first solution to a problem like this is to split up the logic so you work with smaller functions. However, often we don’t have time for refactoring or maybe a big part of the codebase depends on the function’s API being as it is so changing it is a no-no.
An easy way to go around that is to partially apply the function using an utility function or Function.prototype.bind
with some of the arguments up front and using the returned function where necessary.
Having the option to partially apply a given function and reduce the amount of arguments it takes is also useful when we need to “fit” it in certain conditions.
Some functions take a callback with a predefined amount of arguments. But the function you have takes two or three, so you can’t directly pass it in the callback. Instead you need to use an anonymous function.
Not that there is something wrong with that syntax, but as we’ve mentioned earlier simplifying code is one of our top priorities.
Such a situation is a good candidate for a partially applied function. In other words we can preset some of the values and get a function that needs only its last argument. Then we can pass this functions directly to the callback.
We can’t partially apply a function unless we construct it properly in the first place. Something to have in mind here is the order of the arguments that we will be using.
In other words we can’t predefine arguments if they are at the end of the function. So we should construct our functions with that in mind.
Some libraries like Ramda follow a particular convention in which every function receives the data that it operates last so it can be easily partially applied.
However, there are ways to be flexible with the order of arguments. Some times you inherit a code base and can’t freely modify existing APIs.
Or maybe you’ve got an edge case in which you need to provide them in a different order.
Ramda has an utility function called partialRight
which is used for cases like this one.
I am no guru when it comes to functional programming. Writing down these articles helps me as much as it does to the people reading them.
If there is one thing I’ve learned, however, it is that implementing these techniques is not something that should be forced.
There is no ultimate checklist about what to use depending on the situation. Especially when it comes to a topic with such a steep learning curve.
I can’t really say when would be a good case to use partial application or if you should even use it in the first place. This depends on your team, the project you’re working on and most importantly code readability.
If using currying or partial application would worsen the readability of your code use an imperative approach.
I’ve used those techniques and I’ve seen how beneficial they can be when it comes to code reuse. But I’ve also seen the confusing faces of colleagues when I decided to do something fancy.
The correct answer question here is whether you should be practicing partial application and currying. And my answer here is yes.
Functional programming in many ways is more about unlearning old concepts than about learning new ones. And every time you’re playing around with those techniques your mind will train itself to think in a different manner.
In many ways it will be confusing. You will be unsure why something is working or why it isn’t. But this is a good thing — confusion means you’re doing something new and challenging.
Will learning functional programming make you a better JavaScript developer? Maybe. Will you use those techniques on a daily basis? Most of us won’t. Will it make you a better software developer? Absolutely!
If you found this article helpful, share it with friends or colleagues who are struggling with the same topic. Also, I’ve got a newsletter that you can subscribe to if you want to get notified when I post one of these articles. Claps and feedback are much appreciated!
Functional programming paradigms in modern JavaScript: Function Composition_In the previous two chapters we went through some of the basic paradigms in functional programming — pure functions and…_hackernoon.com
Functional programming paradigms in modern JavaScript: Immutability_This is the second chapter in a series of articles on practical Functional Programming paradigms. If you haven’t read…_hackernoon.com
Functional Programming Paradigms in modern JavaScript: Currying_I remember the exact moment I decided to expand my skillset in functional programming. It was a chilly October evening…_hackernoon.com
Functional programming paradigms in modern JavaScript: Pure functions_JavaScript is one of the most popular programming languages out there. It runs in the browser, on desktop, on mobile…_hackernoon.com