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 thisgetPriceWithTax(price, tax)
and the actual function call would look likegetPriceWithTax(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);
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);
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)
Top comments (4)
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.
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.
Good point, thanks @sgoulas !
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 :)