How to curry a function across an unknown number of parameters

Using a functional approach, you can create a function that "curries" arguments for another function. You will need a way to tell the function to return the value, so in this case, calling the function without passing any arguments will return the result:

function curry(fn, ...values) {
    return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}

The cool thing about this function is that you can pass multiple arguments and/or keep invoking the function (1)(2, 3, 4)(5).

Here's a couple of examples:

function curry(fn, ...values) {
  return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}

function multiplyDivide(...args) {
  return args.reduce((total, next, i) => (i % 2) ? (total / next) : (total * next), args.shift());
}

let x = curry(multiplyDivide)(2)(3, 4)(6)();
console.log(x);

let y = curry(multiplyDivide)(5, 4, 2)(3);
y = y(3, 5)(1)();
console.log(y);

Of course, this example does hint at just simply overloading the multiplyDivide function and passing your values to that when you're ready:

function multiplyDivide(...args) {
  return args.reduce((total, next, i) => (i % 2) ? (total / next) : (total * next), args.shift());
}

const values = [5, 4, 2, 3, 3];
values.push(5, 1);

console.log(multiplyDivide(...values));

It's sort of possible but you need to define the terminating condition because the problem is essentially the same problem as writing a recursive function. The function needs a way to tell whether it should return a function or a value.

How you signal the need for values is up to you. One way of doing it is to check if an argument is passed:

// Using add instead of multiplyDivide to simplify example:

function add (num) {
    function adder (n) {
        if (n !== undefined) {
            num += n;
            return adder;
        }
        else { // terminate
            return num;
        }
    }
    return adder;
}

Now you can do:

var sum = add(1)(2)(3)(4)();

Otherwise it would return a function which you can keep calling:

var x = add(1)(2)(3)(4);
x = x(5)(6)(7);
x = x(8)(9)(10);

var sum = x();

Since in js functions are objects, you can also implement the value getter as a static method. It won't be purely functional but makes the "API" a bit more explicit and easier to read:

function add (num) {
    function adder (n) {
        num += n;
        return adder;
    }
    adder.value = function(){
        return num
    };
    return adder;
}

Which would allow you to do:

var sum = add(1)(2)(3)(4).value();

You can even get fancy by overriding the built-in .valueOf() and .toString() methods:

function add (num) {
    function adder (n) {
        num += n;
        return adder;
    }
    adder.valueOf = function(){
        return num
    };
    adder.toString = function(){
        return '' + num
    };
    return adder;
}

Which would allow you to do:

var sum = add(1)(2)(3)(4) + 5; // results in 15
var txt = add(1)(2)(3)(4) + "hello"; // results in "10hello"

The key here is that you need a way to tell the function to stop returning functions.