“This is the 24th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

The conversion of a multi – parameter function to a unary (one – parameter) function.

A Currization function takes more than one argument at a time. So if you have

greet = (greeting, first, last) => `${greeting}, ${first} ${last}`;

greet('Hello', 'Bruce', 'Wayne'); // Hello, Bruce Wayne
Copy the code

I can write it this way

curriedGreet = curry(greet);

curriedGreet('Hello')('Bruce')('Wayne'); // Hello, Bruce Wayne
Copy the code

How to use it correctly?

The proper use of “curryization” is because some Curry functions are more flexible to use. Currying is great in theory, but calling a function for each argument in JavaScript can be tiring.

Ramda’s Curry function lets you call curriedGreet like this:

// greet requires 3 params: (greeting, first, last)

// these all return a function looking for (first, last)
curriedGreet('Hello');
curriedGreet('Hello')();
curriedGreet()('Hello')()();

// these all return a function looking for (last)
curriedGreet('Hello')('Bruce');
curriedGreet('Hello', 'Bruce');
curriedGreet('Hello')()('Bruce')();

// these return a greeting, since all 3 params were honored
curriedGreet('Hello')('Bruce')('Wayne');
curriedGreet('Hello', 'Bruce', 'Wayne');
curriedGreet('Hello', 'Bruce')()()('Wayne');
Copy the code

Note that you can choose to give more than one parameter at a time. This implementation is more useful when writing code.

As shown above, you can call this function forever with no arguments, and it will always return a function that needs the remaining arguments.

It works the same way

const curry = (f, arr = []) => (... args) => ((a) => (a.length === f.length ? f(... a) : curry(f, a)))([...arr, ...args]);Copy the code

Let’s reframe and appreciate it together.

I also added some statements to the debuggerChrome developer tool to check it out.

curry = (originalFunction, initialParams = []) => { debugger; return (... nextParams) => { debugger; const curriedFunction = (params) => { debugger; if (params.length === originalFunction.length) { return originalFunction(... params); } return curry(originalFunction, params); }; return curriedFunction([...initialParams, ...nextParams]); }; };Copy the code

start

Paste greet and curry into your console. Then you go curriedGreet = Curry (greet) and go crazy.

Pause at line 2

Check the two parameters we saw, originalFunction and greet default initialParams is an empty array because we did not provide it. Move to the next breakpoint, oh wait… That’s it. Yes! Curry (greet) returns only a new function that takes more than three arguments. Type curriedGreet in the console to see what I’m talking about.

When you’re done with this, let’s get a little crazier and say sayHello = curriedGreet(‘Hello’).

Pause at line 4

Before continuing, enter originalFunction and in the console. InitialParams Notice that even though we are in a brand new function, we can still access these two parameters? This is because a function returned from a parent function enjoys the scope of its parent function.

inheritance

After the parent function passes, they leave the arguments to the children. Kind of like inheritance in real life.

Curry originally gave originalFunction, initialParams and then returned a “child” function. These two variables have not been disposed of, because perhaps the child needs them. If he doesn’t, then the field will be cleaned up, because when no one mentions you, that’s when you’re really dead.

Ok, back to line 4…

Check nextParams and see that it is [‘Hello’]… An array? But I thought we said curriedGreet(‘Hello’) not curriedGreet([‘Hello’])!

Correct: we call curriedGreet with ‘Hello’, but thanks to rest syntax we become ‘Hello’ [‘Hello’].

Isn’t it? !

Curry is a general-purpose function that can provide 1, 10, or 10,000,000 arguments, so it needs a way to refer to all of them. Using similar REST syntax to capture every parameter in an array makes Curry ”s job easier.

Let’s skip to a statement in the debugger.

This is line 6, but wait.

You may have noticed that line 12 actually runs before the statement on line 6 of the debugger. If not, check it out. Our program defines a call to curriedFunction in line 5, uses it in line 12, and then our debugger clicks on it in line 6. What does the curriedFunction call?

[...initialParams, ...nextParams];
Copy the code

Bah. Looking at line 5 of Params, you see [‘Hello’]. Both initialParams and initialParams are arrays, so we flattened them and combined them into an array using the handy extension operator nextParams.

This is where good things happen.

If params and originalFunction are the same length, please call them greet with our parameter and we are done. This reminds me of…

JavaScript functions also have length

That’s the magic of Curry! That’s how it decides whether to require more parameters.

In JavaScript, the.length property of a function tells you how many arguments it needs.

greet.length; // 3 iTakeOneParam = (a) => {}; iTakeTwoParams = (a, b) => {}; iTakeOneParam.length; // 1 iTakeTwoParams.length; / / 2Copy the code

If the parameters we provide match the expected ones, we’re fine, just hand them over to the original function and get the job done!

But in our case, the parameters and the length of the function are different. We only provide ‘Hello’ so params.length is 1 and originalfunction. length is 3 because there are three greet parameters: greeting, first and last.

So what happens next?

Well, since the if statement evaluates to false, the code will skip to line 10 and re-call our main Curry function. It receives greet again, this time, ‘Hello’ and goes crazy again.

That’s recursion, my friends.

Curry is essentially an infinite loop of self-calling, parameter-hungry functions that won’t rest until their guests are full. Hospitality.

Go back to line 2

Same initialParams parameter as before, except [‘Hello’] this time. Skip again to exit the loop. Enter our new variable in the console, sayHello. This is another function, still expecting more arguments, but we are getting warmer……

Let’s turn up the heat sayHelloToJohn = sayHello(‘John’).

We’re on line 4 again, and nextParams is [‘John’]. Skip to the next debugger on line 6 and check params: it’s [‘Hello’, ‘John’]! ?

Why is that?

Because remember, line 12 says “Hey curriedFunction, he gave me ‘Hello’ last time and ‘John’ this time. Bring them both into the formation […initialParams,…nextParams].”

Now the curriedFunction will compare originalFunction with the length params again, because 2 < 3 we move to line 10 and Curry calls again! Of course, we pass greet our two parameters, [‘Hello’, ‘John’].

We are so close, let’s finish it all and get full greetings!

sayHelloToJohnDoe = sayHelloToJohn('Doe')

I think we know what’s going to happen.

conclusion

Greet gets his argument, Curry stops the loop, and we receive our greeting: Hello, John Doe.

Play with this feature more. Try supplying more than one parameter at a time, or none at all, and go as crazy as you want. Curry looks at how many times you must recurse before returning the expected output.

curriedGreet('Hello', 'John', 'Doe');
curriedGreet('Hello', 'John')('Doe');
curriedGreet()()('Hello')()('John')()()()()('Doe');
Copy the code