no, it has nothing to do with the Indian spice


Currying is a topic that often sits in the more advance user circles of JavaScript. It extends beyond the usual usage of functions and methods and starts to dive into the structural side of code.

When you start to build more complex applications, you start looking into your toolbox for architecture and structural knowledge kit sets to help keep your team’s code sanity intact and ensure a certain level of clean code. Currying is one of these methodologies.

So what is currying? How does it work? Why does it matter? and how do you apply it in your functions?

But before we get into all that, we need to first talk about functional programming.


A quick primer on functional programming…

By design, JavaScript is multi-paradigm. This means that it doesn’t conform to just one single pattern of coding. You can mix and match from a range of patterns and functional patterns are one of them.

When we start learning about code, we’re often told that everything is an object. But the truth is, not everything is an object. There are certain things that just simply don’t fit into the object-oriented way of thinking.

Function programming is a style of writing code that involves a pattern of passing functions as arguments, and the ability to return functions without causing side-effects.

Immutability is one of functional programming’s best features. 

The ability to pass and return functions is done through one of three concepts — pure functions, higher-order functions, and currying.


What is currying?

No. We’re not talking about the Indian spice. Rather, we’re talking about the process where a function takes multiple arguments one at a time. 

So rather than having a function that looks like this:

fakeFunction('param1', 'param2', 'param3');

You end up with something like this:

fakeFunction('param1')('param2')('param3');

What happens here is that when you pass in a parameter, the first function processes it then returns a function that processes the next parameter. This lets you chain your arguments in a way that prevents it from having any side-effects.

How?

When you apply functional programming ideas to your code, your function does one thing and one thing only — result in an output that can’t be disputed. The shape of your data doesn’t change. Mutability caused by side effects is reduced to zilch. 

When you have more than one argument, you’re setting up yourself to potential side effects. However, when you curry your code, your first argument returns an expected outcome that proceeds to process your next argument — and so on, so forth.

A curried function can look something like this:

function fakeFunction(param1){ 
//do something
return (param2) => {
//do something
return (param3) => {
return finalResult;
}
}
}

The final function in the chain has access to all the arguments in the chain. 

The fun part with curried functions is that you still have access to the functions inside the curried function. 

How?

Like this.

let someParam = fakeFunction(param1);
let anotherParam = someParam(param2);
//and then when you call it...
console.log(anotherParam(param3));

This means that regardless of how it’s called, as long as the sequence is correct, the final result will always return as expected.

And that’s the basic structure of currying…but…


How and where would you use currying in your JavaScript code?

Let’s say you have a bunch of functions that need to perform in a particular order. You could, in theory, place all the code in one function — but that would just end up causing chaos in the long run.

What you want are nice, light and clean looking functions that aren’t so long-winded to a point that it gives your IDE and your brain a mini-meltdown.

Currying lets you do this.

It lets you compose the sequence of your functions and ensures that the particular sequence is enforced and followed. The final output is only returned when all the dependencies have been passed through.

Let’s say you want to achieve the following process:

check if stock exists 
--> check warehouse
--> deduct stock amount

Your curried function may look something like this:

function checkStock(stockID){ 
//some check code
if(err){throw err;}

return (warehouseID) => {
//some check code
if(err){throw err;}
      return(stockDeduct)=> { 
//some check code
if(err){throw err;}
         return stockID 
+ ' from ' + warehouseID
+ ' is reduced by ' + stockDeduct;
}
}
}

And your invocation can look something like this:

let orderItem298 = checkStock('FN9382')('SOUTH')(3);

Yes, you could merge all three functions into one — but then how do you effectively detect issues at every step of the way? Currying lets you do it in an elegant manner.

But what if you’ve got more than two or three steps? Wouldn’t the nest be so deep that it starts to look like the pyramid of doom in disguise?

This is the visual downfall of currying. 

That’s why, as awesome as currying is, you have to be selective about where you apply it.

The point of currying is that if you don’t provide all the parameters for a function, it returns a function that tells you what’s left in the list. In a way, it is a checking method to make sure that you’ve got everything you need before you proceed. 

In a way, it can be used as a precursor before your actual function. For example –

function prepInvoiceLine(stockID){ 
//some check code
if(err){throw err;}

return (warehouseID) => {
//some check code
if(err){throw err;}
      return(stockDeduct)=> { 
//some check code
if(err){throw err;}
return
printInvoiceLine(stockID, warehouseID, stockDeduct);
}
}
}
function printInvoiceLine(stockID, warehouseID, stockDeduct){ 
return stockID
+ ' from ' + warehouseID
+ ' is reduced by ' + stockDeduct;
}
let orderItem298 = prepInvoiceLine('FN9382')('SOUTH')(2);

There are probably better applications for currying — but personally, I use it as a checking tool, especially when things need to be done in a particular sequence. 

Another thing to note is that currying has the ability to repeat itself perpetually. But perhaps that’s for another time as it is out of scope for this piece. 

I hope this has helped cleared up some confusion or frustrations that you might be facing in regard to currying.

Thank you for reading.

Comments

0 comments