Currying and Partial Functions (js)

ref – https://hackernoon.com/currying-in-js-d9ddc64f162e
https://codeburst.io/currying-in-javascript-ba51eb9778dc
https://blog.bitsrc.io/understanding-currying-in-javascript-ceb2188c339

Partial Functions

ref – https://medium.com/@JosephJnk/partial-function-application-in-javascript-and-flow-7f3ca87074fe

Partial application is the act of taking a function which takes multiple arguments, and “locking in” some of those arguments, producing a function which takes fewer arguments. For instance, say we have this function:

base ^ exponent

This is partial application: we create square by making a new function, which just passes its arguments through to another function, adding some hard-coded arguments to that other function.

you can go one step further and create a partialApply function.

Now, some might begin to think that the number of nested functions a curried function has depends on the number of arguments it receives. Yes, that makes it a curry.

I can design the curried function of volume to be this:

So it can be called like this:

const hCy = volume(70);
hCy(203,142);
hCy(220,122);
hCy(120,123);

or

volume(70)(90,30);
volume(70)(390,320);
volume(70)(940,340);

We just defined a specialized function that calculates a volume of any cylinder of length (l), 70.

It expects 3 arguments and has 2 nested functions, unlike our previous version that expects 3 arguments and has 3 nesting functions.

This version isn’t a curry. We just did a partial application of the volume function.

Currying and Partial Application are related, but they are of different concepts.

Partial application transforms a function into another function with smaller arity.

Currying

Named after Haskell Brooks Curry, currying is the process of breaking down a function into a series of functions that each take a single argument. In other words, Currying is a technique of evaluating function with multiple arguments, into sequence of function with single argument.

In other words, when a function, instead of taking all arguments at one time, takes the first one and return a new function that takes the second one and returns a new function which takes the third one, and so forth, until all arguments have been fulfilled.

That is, when we turn a function call add(1,2,3) into add(1)(2)(3) . By using this technique, the little piece can be configured and reused with ease.

Why it’s useful ?

Currying helps you to avoid passing the same variable again and again.
It helps to create a higher order function. It’s extremely helpful in event handling.
Little pieces can be configured and reused with ease.

Currying example

Here’s a simple example. We’ll write a function sum3 takes three numbers and returns their sum.

In a standard way, the function is implemented like so:

However, if we provide too few parameters, or too many parameters, then it can have unintended consequences.

add(1,2) –> NaN
add(1,2,3,4) –> 6 //Extra parameters will be ignored.

The curried version of sum3 behaves a differently. It accepts one argument and returns one function. The returned function also accepts one argument and also returns another function that also accepts one argument and …

This cycle continues until the returned function accepts the last argument. The last one in the chain, finally returns the sum.

This works because JS supports closures.

Currying is a transform that makes f(a,b,c) callable as f(a)(b)(c). JavaScript implementations usually both keep the function callable normally and return the partial if arguments count is not enough.

Another example of why currying is useful

Of course, currying comes in handy when you want to:

1. Write little code modules that can be reused and configured with ease, much like what we do with npm:

For example, you own a store🏠 and you want to give 10%💵 discount to your fav customers:

When a fav customer buys a good worth of $500, you give him:

You see that in the long run, we would find ourselves calculating discount with 10% on a daily basis.

We can curry the discount function, so we don’t always add the 0.10 discount:

Now, we can now calculate only with price of the goods bought by your fav customers:

Again, it happens that, some fav customers are more important than some fav customers- let’s call them super-fav customers. And we want to give 20% discount to our super-fav customers.

We use our curried discount function:

We setup a new function for our super-fav customers by calling the curry function discount with a 0.2 value , that is 20%.

The returned function twentyPercentDiscount will be used to calculate discounts for our super-fav customers:

2. Avoid frequently calling a function with the same argument:

For example, we have a function to calculate the volume of a cylinder:

To resolve this, you curry the volume function(like we did earlier):

We can define a specific function for a particular cylinder height:

How does Curry work?

Currying works by natural closure.The closure created by the nested functions to retain access to each of the arguments.So inner function have access to all arguments.

Additional Examples

ref – https://www.sitepoint.com/currying-in-functional-javascript/

You can see how powerful this approach is, especially if you need to create a lot of very detailed custom functions.
The only problem is the syntax. As you build these curried functions up, you need to keep nesting returned functions,
and call them with new functions that require multiple sets of parentheses, each containing its own isolated argument.
It can get messy.

To address that problem, one approach is to create a quick and dirty currying function that will take
the name of an existing function that was written without all the nested returns.
A currying function would need to pull out the list of arguments for that function,
and use those to return a curried version of the original function:

Currying is an incredibly useful technique from functional JavaScript.
It allows you to generate a library of small, easily configured functions that behave consistently,
are quick to use, and that can be understood when reading your code. Adding currying to your coding practice
will encourage the use of partially applied functions throughout your code, avoiding a lot of potential repetition,
and may help get you into better habits about naming and dealing with function arguments.