Partial Application of Functions
Providing function with fewer arguments than it expects is called Partial Application of functions.
While the concept is simple, it can be used to prepare stronger Functional Constructs in our everyday JavaScript.
Often I am asked: “Why in the world would you apply a function partially?”
“Because the logic I get after that is a thing of Beauty and Functional Purity.”
We call a function with fewer arguments than it expects and It returns a function that takes the remaining arguments. And this is called Partial Application of Functions.
Using function.bind()
This style of Partial Application is not functionally cool, but I still want you to know about this.
We created a function ‘add’ which accepts two arguments.We preloaded it with a single argument and created a function ‘increment’ which takes only one argument.We created another function by the same process of Partial Application, this time by applying a different argument.At last, we called our preloaded functions with the final argument.
Binding a function to fewer arguments helps us in generating other functions to make our code less repetitive and more definitive. But there are some problems with that, and those are apart from not being functionally cool.
- Too Unpredictable: Function.bind will always return another function even if we have supplied all the arguments to the base function. So we couldn’t know when to stop.
- Noticed that ‘null’ in the code, that’s the context of the partially applied function we have to pass as the first argument of bind. So, we are forced to attach the context, every time we apply a function partially. Not Cool!
Currying
It’s an awesome Functional Programming technique that can be achieved in JavaScript due to its ability to create Higher Order Functions. Currying is not Partial Application of function, but it helps in achieving the same goal in more functional manner.
Currying over binding
- Predictable: A curried function is made such that it will always return another function which takes only one argument.
- Awesome: A curried function always remembers the arguments applied because of the closure. And they look so good when written as λ Expressions. 😎
- Pure: A curried function is always pure as it generates the same function for the same input.
Functional Purity
A curried function is always pure as it generates the same function for the same input.
Currying is a Batman’s utility belt for a functional programmer and we’ll see how it’s important.
Now, I want you to have a look at this code.
‘Hello’.replace(/Hello/g, ‘Bye’).concat(‘!’);
This construct is called Method Chaining and is known to be a good Object Oriented Design. Now, if you look closer you can see how it’s working and what it lacks.
‘Hello’, the data is being piped through the chain of compatible methods and we can chain more methods as long as the returned object is compatible with the method being chained.
So, this can go on like this.
‘Hello’
.replace(/Hello/g, ‘Bye’)
.concat(‘!’)
.repeat(2)
.split('!')
.filter(x=>x!='!')
.map(x=>'Hello').toString();
The above construct is possible because of the ‘Hello’ object provided, all the methods that are chained are worthless without the object provided to them. That’s sad. The problem with this or I can say with every Object Oriented Design is that everything revolves around Objects, everything depends on data.
Let’s functionalise this,
concat('!',replace(/Hello/g,'Bye','Hello'));
Well, this looks a little less readable, don’t worry it’s functional programming, For cases like this, we have Function Composition.
Function composition is the process of combining two or more functions to produce a new function.
Okay, so we can use Function Composition to combine our replace and concat functions, for that we need a composer function.
Let’s compose our functions, but wait we have a problem, our composer works on functions with only one parameter but our functions replace and concat clearly takes more than one parameter.
Time for our favorite technique, currying
Now, I need you to carefully examine how I strategically curried my functions so that the only argument remaining to be applied is the “data” to operate upon.
Finally,
compose(replace(/Hello/g,’Bye’),concat(‘!’))(‘Hello’)
And this can go on like this,
compose(
replace(/Hello/g,’Bye’),
concat(‘!’),
repeat(2),
split('!'),
filter(x=>x!='!'),
map(x=>'Hello'),
toString
)(‘Hello’)orprocessHello(‘Hello’)
And this is cool at so many levels. For Example, since our functions no longer depend upon the data provided, we can do this.
[‘Hello’,’Hello world’,’Hi’].map(processHello)
I am so sorry, I mean
map(processHello)(‘Hello’,’Hello world’,’Hi’)
Hey, congratulations we just wrote a point-free style function. Do you see no “ . ”.
Well, point-free style functions are those that do not mention data upon which they operate. This style of writing functions is called Point-free style or Tacit Programming. As per Wikipedia
Tacit programming, also called point-free style, is a programming paradigm in which function definitions do not identify the arguments (or “points”) on which they operate. Instead, the definitions merely compose other functions, among which are combinators that manipulate the arguments.
Currying and Composition play very well to create this style.
Currying prepares functions to take only data as their argument(the rest arguments being partially applied beforehand) and Composition helps in combining those partially applied functions so data can pipe through them.
And this style, this point-free style of writing functions is a litmus test of Functional Purity. As it confirms that our code constitutes of smaller Pure Functions otherwise we won’t be able to compose them.
See, I told you the results are Pure and that’s why you apply functions partially.
Imagine Batman without his utility belt, Functional Javascript is just not possible without Currying, that’s the reason why popular functional programming libraries like lodash/fp or Ramda comes with auto-curried functions.
Written with 💖.
Thanks for reading.
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!