Sometimes when writing complex programs, headaches and frustration can feel like unavoidable parts of the developing process. As I continue to learn and build my toolkit for writing clean, structurally sound code, I constantly find new methodologies that streamline my logic and help me avoid those pesky headaches. One of the latest tools I’ve discovered is currying.
Currying is a functional programming technique which transforms a function that takes multiple arguments into a sequence of nesting functions that each take only a single argument.
Instead of taking all its arguments up front, the function takes only the first argument and returns a new function that takes the next argument, repeating this process until all arguments are exhausted. When the final function in the currying chain is returned, every argument that was passed in is kept accessible and used in the execution due to closures. The number of arguments passed into a function is known as that function’s arity, and keeping arity to a minimum comes with several benefits.
We have a basic function getPyramidVolume that takes a length, width and height of a pyramid and returns the pyramid’s volume.
We can “curry” this function to accept a single argument, and return a function which itself will accept a single argument, and then return a function (which will take…a single argument 🤭). This loop continues until the last function is returned, and that final function performs the calculation with the argument it accepted as well as the previous arguments that were passed in.
In this example, I passed the add function through _.curry to create a curriedAdd function. I can now use curriedAdd as a module to create other functions, such as addTwo, which can accept however many arguments I pass in.
The idea with currying is that your function can pass through the application and gradually receive the arguments it needs. This is super useful for a few different reasons. By decreasing arity, you decrease the potential of unwanted side effects. Currying your code allows you to pass in a first argument that will return an expected and undisputed outcome, which then goes on to process your next argument, and so on, until all your arguments have been received. This also boosts the modularity of your code. By breaking a rigid function down into smaller components that can be reused and reconfigured with ease, your code is easier to read, easier to fix, easier to manage and easier to reuse. It’s hard to see why anyone wouldn’t love such a powerful technique.
To sum things up, currying allows us to transform a clunky function that takes multiple arguments into a smoother one that instead takes only a single argument, and this “magic” happens thanks to closures. Just like different spices can be added in different stages of the cooking process to make a delicious curry, our newly curried functions can be more easily broken down into their essential parts, and then sprinkled throughout our program to achieve our desired functioning.