What Is Currying Actually Useful For in Functional Programming?
Functional programming has been increasingly active lately. When I was interning last year, I bought a copy of “Functional Programming in JavaScript,” read through it hastily with only a vague understanding. After re-reading it this year, I’m writing this blog post to share my understanding of currying.
A curried function returns a new function for each logical argument. (Functional Programming in JavaScript)
Simply put, currying is the process of reducing the arity of higher-order functions. For example, transforming: function(arg1,arg2) into function(arg1)(arg2) function(arg1,arg2,arg3) into function(arg1)(arg2)(arg3) function(arg1,arg2,arg3,arg4) into function(arg1)(arg2)(arg3)(arg4) … function(arg1,arg2,…,argn) into function(arg1)(arg2)…(argn)
let curryAddMultiply = curry3(normalAddThenMultiply); let curryAdd2Multiply = curryAddMultiply(2); let curryAdd2Multiply3 = curryAdd2Multiply(3);
curryAdd2Multiply3([1, 2, 3]); // [9, 12, 15]
What Is Currying Actually Useful For
Each step is an explicit call (consuming one argument), while caching the result of that step (returning an anonymous closure that awaits the next argument), thereby deferring the call. When the time is right, the next argument can be passed to continue the invocation.
// Used to define a series of actions actionList = [{ "action": "isLogin", "hasCallback": true }, { "action": "doLogin", "hasCallback": false }, { "action": "setTitle", "hasCallback": true }];
// Factory function for batch-generating APIs factory(actionList) { for (let value of actionList) { this[`${value.action}`] = this.generator(value); } }
// Simplified API generator function generator(action) { returnfunction(params) {
// Final usage, where params are passed by the user at call time bridge.setTitle({skin: 'red', color: '#666'}) .then((data) => { alert(data); }) .catch((err) => { alert(err); });
This middleware expects a first argument { dispatch, getState } and returns an anonymous function expecting a next parameter. Since the value of next is determined by the previous middleware, the call is deferred until the next parameter is passed. Finally, it returns a new function (the enhanced dispatch function with middleware), which expects an action parameter.