DEV Community

Yigal Ziskand
Yigal Ziskand

Posted on • Updated on

Clean Code with Currying (3 min recap)

Motivation

In order to improve code readability currying technique may be applied.

By modifying our code with such technique we shall gain cleaner and more readable function names.

As a result our code-base will became easier to maintain.

Basic Idea

There are multiple principles where currying technique may be utilized... We will look into one particular example of implementation with the almighty closures.
As we claimed above - utilizing currying should improve our code readability, so let's try to modify some imaginary tax calculations function (function expects two input parameters and provides an output of total calculation).
It's declaration could probably look like this getPriceWithTax(price, tax) and the actual function call would look like getPriceWithTax(50, 10) - yeah... its less explicable once we don't see the actual input parameter names...

We going to apply currying technique to improve the readability so our code could become something like getPriceWithTax10(price), getPriceWithTax5(price), getPriceWithTax20(price) and etc...

I believe you got the idea.

Pseudo Code

    // utilize currying technique
    taxCalculation = (tax)

    // improve core readability
    getPriceWithTax10 = taxCalculation(10)

    // enjoy the improved redability
    priceTaxBy10 = getPriceWithTax10(price);
Enter fullscreen mode Exit fullscreen mode

Code Snippet

    const taxCalculation = (tax) => (price) => price + price * tax / 100;

    const price = 100;

    const getPriceWithTax10 = taxCalculation(10);
    const getPriceWithTax5 = taxCalculation(5);
    const getPriceWithTax20 = taxCalculation(20);

    const priceTaxBy10 = getPriceWithTax10(price);
    const priceTaxBy5 = getPriceWithTax5(price);
    const priceTaxBy20 = getPriceWithTax20(price);

Enter fullscreen mode Exit fullscreen mode

Example

Svelte REPL is such a joy to play with... - so I've sketched a clickable example with the code snippet from above

(for those who loves clickable stuff)

JS Currying (Svelte REPL)

Resources

Top comments (4)

Collapse
 
imjb87 profile image
John Bell

I don't understand how this is anymore semantic than the original example you posted of a function that takes two parameters. In many countries tax is a constant aswell and not a variable.

Collapse
 
sgoulas profile image
sgoulas

Generally speaking currying is good when you have a complex function that can be broken up in smaller ones. If you curry it as a series of functions it is easier to make changes to the subfunctions rather to the large one. Also, it allows you to use the newly created subfunctions in other parts of the code, so instead of a big function that explicitly calls smaller functions you have a pipe of functions that the result of the one gets fed into the other. This also means you can remove or add new functions in the pipe much more easily than refactoring the big function.

Collapse
 
ziskand profile image
Yigal Ziskand

Good point, thanks @sgoulas !

Collapse
 
ziskand profile image
Yigal Ziskand

Hi John! Thanks for the comment!

Refactoring the initial function f(x,y) into f(x)(y) can be beneficial in multiple factors - if "x" parameter is constant (as you mentioned that tax in many countries is constant), then there is no need to repeat the procedure of providing it over and over as an input..
you can benefit by applying currying technique and simply create constant function of f_with_x() and apply it on the other parameter which is most likely dynamic f_with_x(y)

I believe it can be very beneficial if you maintain some OSS project or maybe some public library [let consumers of your code make less mistakes...]

Imagine - as if priceWithTax(100, 10) can be mistakenly written as priceWithTax(100, 100) while priceWithTax10(100) hides the details of tax input and tax calculation.
In that particular case we gain readability, code reuse, hide unrequested implementation details.

Hope i made it a bit cleaner :)