Saturday, January 24, 2015

JavaScript Currying

Generic currying in JavaScript is so great but it takes time to understand the code. Closures!

'use strict';

// subCurry(fn, 1)(2, 3)
var subCurry = function (fn /* Multiple arguments possible */) {
  var args = [].slice.call(arguments, 1); // Dont take the first argument
  return function () {
    var thisArgs = Array.prototype.slice.call(arguments);
    return fn.apply(this, args.concat(thisArgs));
  };
};

// curry(fn)(1)(2)(3)
var curry = function (fn, length) {
  // Length will only be available after the first curry
  length = length || fn.length;
  return function () {
    if (arguments.length < length) {
      var thisArgs = Array.prototype.slice.call(arguments);
      var combined = [fn].concat(thisArgs);

      return curry(subCurry.apply(this, combined), length - arguments.length);
    } else {
      // All arguments ok
      return fn.apply(this, arguments);
    }
  };
};

var fn = function(x, y, z) { return x+y+z; }

var mFn = curry(fn);
console.log(mFn(1)(2)(3));