1

I generally understand currying and how it uses closures:

function foo(a) {
  return function(b) {
     return function(c) {
         return a*b*c;
     }
   }
}

how would this be maximized though? Wouldn't this only save operational time if this were expecting to receive a lot of the same arguments?

For example, if you knew 5 would always be the first argument:

let first = foo(5);

then you can do: first(8)(12); or whatever else for the last 2 arguments.

However if you are not expecting the same arguments and you just use it as follows every time:

foo(3)(5)(9);

doesn't that defeat the purpose and is the same thing as making a normal function that just takes 3 arguments?

I am just trying to grasp the use case for this because in my head, it seems really limited.

  • 1
    Well it sometimes makes sense when you build helper functions to create calbacks for other functions, e.g. `array.sort( sortBy("name") )`. In a lot of cases however it makes more sense to just have one function with multiple parameters. So you are right,it is very limited. – Jonas Wilms Dec 13 '20 at 19:45
  • Ideally you'd use autocurrying so you can use the function in any way you want like `f(a, b)(c)` and it should all work the same. See Lodash `curry` for example. – elclanrs Dec 13 '20 at 19:49
  • https://stackoverflow.com/a/37764035/3757232 – Jared Smith Dec 13 '20 at 19:49

2 Answers2

2

Its usefull when doing partial application or composing. You can do something like this for example

const arr = [1,2,3,4]

const curry = (fn, ...a) => fn.length > a.length ? (...b) => curry(fn,...a.concat(b)) : fn.apply(null,a)

const add = curry((a,b) => a+b)

console.log(arr.map(add(5)))

const compose = (...fns) => fns.reduce((f,g) => b => f(g(b)))

console.log(arr.map(compose(add(5),add(2))))
ptothep
  • 415
  • 3
  • 10
1

Here's a couple of real-world examples where I use this all the time. First, on the front end:

debounce(someEventHandler, someTimeout);
debounce(someOtherEventHandler, someTimeout);
debounce(yetAnotherEventHandler, someTimeout);

Let's say that I want all my keyboard handlers debounced by 250ms. I can write that over and over, or...

const debounceBy250 = curry(flip(debounce))(250);

Now the code is more concise and clearer. Secondly, on the backend let's say that you've got code that gets a request (database, REST, TCP, whatever) timeout from an environmental variable. Just like above, you can either add that every place it's used, or you can partially apply it to the functions that take it.

For a case where someone was actually using it but didn't know what it was called, see my answer here on this not quite a duplicate question.

Jared Smith
  • 19,721
  • 5
  • 45
  • 83