Currying
— JavaScript, Functional Programming
Before we learn what currying is, let's focus on the other important definition from the functional programming world.
Arity is a number of function arguments, it's also called function length, a number of function arguments are proportional to its complexity.
In an ideal world, all functions would be pure and they would take one argument. Functions like these are great because they do one thing. Additionally, they are more flexible and more powerful than their colleagues with more arguments.
However, in our programs, we can come across the functions that usually have a length that is larger than one. But it doesn't mean that we should resign from unary functions. To solve this problem we use a technique that is called currying.
Currying is a technique that depends on transforming a function that expects many arguments into a sequence of functions with one argument. A curried function will return the final result only when all expected arguments will be passed. When the arity is less than expected, instead of evaluating the function, the received value will be a function that takes the rest of the remaining arguments.
1function foo (a, b, c) { return d }23foo(a) -> foo(b, c)45foo(a,b) -> foo(c)6foo(a)(b) -> foo(c)78foo(a,b,c) -> d9foo(a,b)(c) -> d10foo(a)(b)(c) -> d
Some languages that based on FP paradigm like F#, Haskell or Elm supports currying by default.
In JavaScript this mechanism is not supported by default, because when we call a function without some arguments,
the engine will set for these values undefined
and the function will be normally executed.
Of course, there are plenty of libraries e.g Lodash or Ramda that provides this functionality, but this mechanism can be easily created by hand.
Typing in Google phrase gist curring js
we can find some snippets that present the implementation of currying.
I came across on below implementation here.
This implementation it's concise and really easy to understand thanks to ES6 features.
1const curry = (fn, ...args) =>2 fn.length <= args.length ?3 fn(...args) :4 (...more) => curry(fn, ...args, ...more);