12

I was struggled to find a real-life example of using curry function and get the benefit of using curry.

When I google curry function I often see the example like

let add = x => y => x + y;
let add10 = add(10);
console.log(add10(20));

I have to say I really don't see the value of using curry in this example.

After reading through the answers in this SO https://stackoverflow.com/questions/113780/javascript-curry-what-are-the-practical-applications I still don't see the benefit of using it.

For example, the highest score answer give an example of converter, but that example can be rewrote without curry as another answer shows.

I also read through the answers What is the advantage of currying? (although the discussion are not confined to javascript) I still get the feeling that the curry version can be rewrote without curry(in js).

So can someone show me the "real" advantage/benefit of using curry in javascript?

--- update 2021.10.22 ---

I want to provide an answer to my own question because now I have a better understanding of curry. But the question was closed so I provide this update as my answer.

Only after I study Ramda, which uses curry function as the basic building block, do me finally appreciate the usefulness of curry.

Reading the articles on the ramda website like Why Curry Helps, Favoring Curry, Why Ramda? showing how to put "function first,data last", we then can chain a group of functions together and get the final version of a function that work on data directly.

So to answer my own question "A real-life example of using curry", the example of the promise chain in to process data in "Favoring Curry" is a very good one (although with async/await it may not to seem too appealing)

To Robert Harvey, can you please not to delete my update this time or let me know how can I answer it ?

2 Answers2

15

Currying in your example doesn't really make sense, I agree. To see the functionality of currying, you need to combine it with higher order functions: functions that takes another functions as parameter.

The most typical example of this is map, filter, and reduce, though another common situation is callbacks. When you partially apply a function, you can pass the partially applied function to these higher order functions. Currying makes sense when most of the time you'd want to use a function is for a partial application so that it can be passed to another higher order function.

A more illustrative example might look like so:

let array1 = [1, 4, 9, 16];
let add = x => y => x + y;
array2 = array1.map(foo ? add(10) : add(20));

Currying is never necessary, yes, as you can always create an anonymous/arrow function from a regular function when you need them, but in some situations it can be very convenient to have curried function compared to regular (and in other situations, it's just making things annoying and slow).

Lie Ryan
  • 12,496
11

I've hardly ever used Currying myself, but here's a recent example where it proved useful. I was coding for the game Battlesnake, but this would apply to many games. They provide you with various arrays, giving the location of your snake, enemy snakes, and food. Let's say you are considering a move to a certain {x,y} point, and you want check if it contains another snake, food, or even yourself. The first pass would be to write code like this (I'll use a mix of function and new fangled arrows)

// utility function
function samePoint(p1, p2) {
  return (p1.x === p2.x) && (p1.y === p2.y);
}

and somewhere in the code go

let possibleMove = {x,y}; // where you are thinking of moving
...
if (foodArray.some((p) => samePoint(p, possibleMove )) {
  // this move looks tasty, give it a bonus value...
}

Not bad, but, since you will doing this many many places in your code, a bit tedious and clunky. And, from my experience, easy to mess up the two arguments. :-( The underlying problem is that some() (or find()) accept a function taking only a single argument, and you really need two arguments, the two points. So, you think of currying! Here many would use arrows, I find nested functions clearer:

function samePointAs(p1) {
  return function(p2) {
    return samePoint(p1, p2);
  }
}

Then, your "is that food" test becomes

let possibleMove = {x,y}; // where you are thinking of moving
...
if (foodArray.some(samePointAs(possibleMove )) {
  // this move looks tasty, give it a bonus value...
}

Is this going to make you an Internet millionaire? Probably not. But it does simplify, and, in this case, clarify your code.

user949300
  • 9,009