I can’t remember who exactly was the guest but he talked in length about how functional programming has helped his team and the problems they have solved for the product they are developing.
It sounded really interesting so I got home and did some Googling to see what this functional thing was about and what is so special about it. I was able to maintain my composure while I was going through the idea of pure functions and even immutable data structures.
But at one point I reached an explanation of currying and quickly discarded it as something I would never do in a project. I just couldn’t grasp the idea behind it.
Functional programming has a steep learning curve, but the slope gets even harder to climb when you pass the fundamental knowledge. I doubt I’m the only one who’s felt that way, so in this article we will try to examine currying in the simplest manner.
What is currying?
Currying is a technique used to construct functions in a particular way. If you’ve read some other articles about functional programming you have undoubtedly seen it mentioned together with partial application.
In the scope of this article we will focus entirely on currying, why it’s useful and how to apply it.
We already know that we should compose our program mostly of pure functions to contain side-effects as much as possible. And we know that pure functions take arguments as input and return output based on those arguments.
Now, there are functions of different arity. Arity is a term which specifies the amount of arguments that a function takes. For example a function which takes a single number as an argument has an arity of one. A function which takes two numbers or two strings, or a string and a number has an arity of two and so forth.
Currying is a technique which helps us to transform a function with an arity higher than one into a series of functions each with arity of one.
This is all the terminology that we will need to understand currying. Instead of using a single function which takes a couple of arguments (function with arity of two), we will use currying to transform it into two chained functions that each have an arity of one.
A simple example
I try to stay away from mathematical examples because they are so common and often inapplicable in an actual project, but for most functional programming concepts a mathematical explanation is the simplest one.
The first add function takes two arguments and returns their sum. Nothing we’ve never seen here.
The addCurried function on the other hand looks like it’s doing some dark magic at first glance and the multiple => signs can be mighty confusing at first.
Let’s walk through what happens in the curriedAdd function. It first takes an argument x and it returns a function. It does not do any calculations at this point.
The function that gets returned takes an argument y and returns the sum of y with x from the previous function.
Now this can be a bit confusing at first, especially if you are new to the language and don’t fully understand closures. To summarise, a closure is a nested function which can access its lexical scope even when it’s called outside of it.
So when we create the function addTwo, even though it takes only a single argument, because it has a closure over curriedAdd it will still have access to x and therefore invoking it will return their sum.
The way this works will get a lot clearer with an example that uses the old function syntax.
Why is this useful?
Currying seems incredibly unnecessary at first mainly because we are illustrating it with an operation as simple as adding two numbers. This technique is powerful because it gives us better control over our functions.
By having more control over a function we can write more descriptive code and achieve much better code reusability. Look how easy the addTwo function call is to understand. It basically reads like plain english.
Currying is useful every time we want to use more abstract functions and hide the implementation. A more applicable example would be some curried async operations.
There are a few important things that we need to note here. First is how we abstract away the actual call to the service. Each function provides another layer of abstraction on top of the previous so in the end saving an article is as simple as just passing the object to the saveArticle function.
The function itself looks a bit more complex to someone who hasn’t encountered the currying technique before, but using it actually improves the simplicity of our code. We needn’t worry about the order of the arguments because every function can take exactly one.
Then we should also note the flexibility that we achieve. Most programs will probably need to make more POST requests, so the makePostRequest function can be reused for our different entities.
If we take advantage of arrow functions we can drastically decrease the amount of code we need to write curried functions and at the same time drastically increase the complexity of our work.
This looks really clean once you are familiar with the concept but for anyone reading your code without understanding currying it will bring more headache than anything else.
What should be curried?
Purely functional languages such as Haskell have their function curried by default. You simply cannot invoke a function with multiple arguments, so every function you create will be automatically curried.
Whether you will be using currying depends entirely on your team’s opinion and knowledge of functional programming. Whether your team is excited or skeptic about this programming technique will tilt the scales in one direction or another.
What I would suggest is to read about the topic, practice it but never force it. It is common to try to implement a new pattern or technique we’ve learned recently. As the saying goes, if you have a hammer everything starts looking like a nail.
We can force our functions to be pure, we can force immutability by integrating ImmutableJS in our Redux store, but when it comes to currying and partial application (we’ll get into this next time) — only use those techniques when there’s a clear benefit.
The main goal of functional programming is to write more descriptive code. It’s supposed to make us think less and benefit from the abstractions that it provides. If using normal functions with a few arguments will make for a better developer experience then we should always do that.
In this article we covered the basics of currying, a functional programming technique which helps us split functions into smaller ones — each taking a single argument.
We discussed some benefits and walked through some code. We saw how we can use functions to their full extent and I plan on continuing with a similar technique called partial application.
If you haven’t read the previous articles, they are linked here. If you want to get an email when I post something like this you can subscribe from here. Hope this was helpful, don’t forget to share it with friends and hold the clap button!