JS Curry function with Recursion JS Curry function with Recursion arrays arrays

JS Curry function with Recursion


Here's a generalized solution that works by repeatedly calling bind until enough parameters have been passed.

function curry(func, arity = func.length) {  return function (...args) {    if (args.length >= arity) {      return func(...args);    } else {      return curry(func.bind(this, ...args), arity - args.length);    }  };}const multiply = curry((a, b, c) => a * b * c);console.log(multiply(2, 3)(4));console.log(multiply(2)(3, 4));console.log(multiply(2)(3)(4));console.log(multiply(2, 3, 4));


Your code

var multiply = function(...args) {    if (args.length === 3) {        return args[0] * args[1] * args[2];    } else {        return function() { // ***            args.push([].slice.call(arguments).pop()); // ***            return multiply.apply(this, args);        };    }}

*** these two lines needed changing, you were almost there, so tantalisingly close in fact

var multiply = function(...args) {    if (args.length === 3) {        return args[0] * args[1] * args[2];    } else {        return function(...args2) { // ***            args.push(...args2); // ***            return multiply.apply(this, args);        };    }}console.log(multiply(2, 3)(4))console.log(multiply(2)(3, 4))console.log(multiply(2)(3)(4))console.log(multiply(2, 3, 4))

ES6 makes it even cleaner

const multiply = (...args) => (args.length === 3) ? args[0] * args[1] * args[2] : (...args2) => multiply(...args.concat(args2));console.log(multiply(2, 3)(4))console.log(multiply(2)(3, 4))console.log(multiply(2)(3)(4))console.log(multiply(2, 3, 4))


Here's an answer similar to 4castle's that uses an additional rest parameter instead of Function.prototype.bind

const curry = (f, ...xs) => (...ys) =>  f.length > xs.length + ys.length     ? curry (f, ...xs, ...ys)    : f (...xs, ...ys)    const multiply =  curry ((a, b, c) => a * b * c)console.log (multiply (2, 3) (4))         // 24console.log (multiply (2) (3, 4))         // 24console.log (multiply (2) (3) (4))        // 24console.log (multiply (2, 3, 4))          // 24console.log (multiply () () () (2, 3, 4)) // 24

But relying upon the length property is a function can be a problem when variadic functions come into play – Here, partial is easier to understand, explicitly communicates when a function's arguments will not be supplied in entirety, and it works with variadic functions.

const multiply = (x, ...xs) =>  x === undefined    ? 1    : x * multiply (...xs)const partial = (f, ...xs) =>  (...ys) => f (...xs, ...ys)console.log (partial (multiply) (2, 3, 4))    // 24console.log (partial (multiply, 2) (3, 4))    // 24console.log (partial (multiply, 2, 3) (4))    // 24console.log (partial (multiply, 2, 3, 4) ())  // 24console.log (multiply (2, 3, 4, 5, 6, 7))                     // 5040console.log (partial (multiply, 2, 3, 4) (5, 6, 7))           // 5040console.log (partial (partial (multiply, 2, 3), 4, 5) (6, 7)) // 5040

Partial application is related to currying, but not exactly the same thing. I write about some of the differences in this answer and this one