How to curry a function across an unknown number of parameters

后端 未结 5 2062
灰色年华
灰色年华 2020-12-06 18:40

Say I have a function called multiplyDivide

If I were to call multiplyDivide(2)(3)(4)(6) it would be equivalent to 2 * 3 / 4 * 6

5条回答
  •  醉梦人生
    2020-12-06 19:25

    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.

提交回复
热议问题