If I have a pet hate with the developer community it's that a lot of concepts in technology are simply explained with needless complexity. "Currying" I've found to be one of these ideas. Currying is in it's simplest form pretty simple. Let's take a look at it.
To show you how and why to use currying let us look at an example.
Currying Explained Simply
Whilst refactoring code I saw a good chance to use Currying.
The code I saw looked like this simplified example:
var contains = function(one, two){
// Computation
};
var one = {};
contains(one, "Some string")
contains(one, "A different string");
contains(one, "Another string");
Smelling the code
When writing / reviewing / refactoring code we often look for what is known as a "code smells". A code smell is similar to an anti-pattern. It should stop you in your tracks and make you say "hmmm".
This code gave me a strong whiff of a code smell.
Why? The repetition of the code contains(one
.
A potential upgrade
I immediately started looking for ways to shorten this code.
A possibility to improve would be to hardcoded the one
value inside the contains
function. Like so:
var contains = function(two){
var one = value;
// Computation
};
contains("Some string")
contains("A different string");
contains("Another string");
This does stop the repetition of always passing the first value. but it reduces the reuse of the contains
code.
It couples it to the implementation of the one value.
So how do we reduce this repetition without creating tight coupling?
Enter Currying
In order to prevent the repetition of the first variable we can leverage javascripts closure functionality.
var contains = function(one){
return function(two) {
// Computation
}
};
var boundContains = contains(one);
boundContains("Some string")
boundContains("A different string");
boundContains("Another string");
What's happening here?
- The
contains
function is called once with the variableone
. - The Javascript closure then saves the reference to the one variable in a closure
- The bind contains method is now equivalent to the returned function from inside
contains
- We can now use the bindContains method, without always passing the one parameter.
- If the one value changes, now we have only one reference to update.
Conclusion
This is a simplified example. But hopefully you can see how currying can be used to DRY up our code.
It doesn't have to be so esoteric either.
You can even take currying further by creating a curry
method, but that's a lesson for another day!