How can I make var a = add(2)(3); //5 work?

后端 未结 28 2335
长发绾君心
长发绾君心 2020-11-27 14:11

I want to make this syntax possible:

var a = add(2)(3); //5

based on what I read at http://dmitry.baranovskiy.com/post/31797647

I\

相关标签:
28条回答
  • 2020-11-27 14:39

    This is a generalized solution which will solve add(2,3)(), add(2)(3)() or any combination like add(2,1,3)(1)(1)(2,3)(4)(4,1,1)(). Please note that few security checks are not done and it can be optimized further.

    function add() {
    	var total = 0;
    
    	function sum(){
    		if( arguments.length ){
    			var arr = Array.prototype.slice.call(arguments).sort();
    			total = total + arrayAdder(arr);
    			return sum;
    		}
    		else{
    			return total;
    		}
    	}
    
    	if(arguments.length) {
    		var arr1 = Array.prototype.slice.call(arguments).sort();
    		var mytotal = arrayAdder(arr1);
    		return sum(mytotal);
    	}else{
    		return sum();
    	}
    
    	function arrayAdder(arr){
    		var x = 0;
    		for (var i = 0; i < arr.length; i++) {
    			x = x + arr[i];
    		};
    		return x;
    	}
    }
    add(2,3)(1)(1)(1,2,3)();

    0 讨论(0)
  • 2020-11-27 14:39

    Simply we can write a function like this

        function sum(x){
          return function(y){
            return function(z){
              return x+y+z;
            }
          }
        }
    
        sum(2)(3)(4)//Output->9
    
    0 讨论(0)
  • 2020-11-27 14:41

    Don't be complicated.

    var add = (a)=>(b)=> b ? add(a+b) : a;
    console.log(add(2)(3)()); // Output:5
    

    it will work in the latest javascript (ES6), this is a recursion function.

    0 讨论(0)
  • 2020-11-27 14:42

    With ES6 spread ... operator and .reduce function. With that variant you will get chaining syntax but last call () is required here because function is always returned:

    function add(...args) {
        if (!args.length) return 0;
        const result = args.reduce((accumulator, value) => accumulator + value, 0);
        const sum = (...innerArgs) => {
            if (innerArgs.length === 0) return result;
            return add(...args, ...innerArgs);    
        };
        return sum;
    }
    
    
    
    
    // it's just for fiddle output
    document.getElementById('output').innerHTML = `
    <br><br>add() === 0: ${add() === 0 ? 'true' : 'false, res=' + add()}
    <br><br>add(1)(2)() === 3: ${add(1)(2)() === 3 ? 'true' : 'false, res=' + add(1)(2)()}
    <br><br>add(1,2)() === 3: ${add(1,2)() === 3 ? 'true' : 'false, res=' + add(1,2)()}
    <br><br>add(1)(1,1)() === 3: ${add(1)(1,1)() === 3 ? 'true' : 'false, res=' + add(1)(1,1)()}
    <br><br>add(2,3)(1)(1)(1,2,3)() === 13: ${add(2,3)(1)(1)(1,2,3)() === 13 ? 'true' : 'false, res=' + add(2,3)(1)(1)(1,2,3)()}
    `;
    <div id='output'></div>

    0 讨论(0)
  • 2020-11-27 14:44

    This question has motivated so many answers already that my "two pennies worth" will surely not spoil things.

    I was amazed by the multitude of approaches and variations that I tried to put "my favourite" features, i. e. the ones that I would like to find in such a currying function together, using some ES6 notation:

    const add=(...n)=>{
     const vsum=(a,c)=>a+c;
     n=n.reduce(vsum,0);
     const fn=(...x)=>add(n+x.reduce(vsum,0));
     fn.toString=()=>n; 
     return fn;
    }
    
    let w=add(2,1); // = 3
    console.log(w()) // 3
    console.log(w); // 3
    console.log(w(6)(2,3)(4)); // 18
    console.log(w(5,3)); // 11
    console.log(add(2)-1); // 1
    console.log(add()); // 0
    console.log(add(5,7,9)(w)); // 24
    .as-console-wrapper {max-height:100% !important; top:0%}

    Basically, nothing in this recursively programmed function is new. But it does work with all possible combinations of arguments mentioned in any of the answers above and won't need an "empty arguments list" at the end.

    You can use as many arguments in as many currying levels you want and the result will be another function that can be reused for the same purpose. I used a little "trick" to also get a numeric value "at the same time": I redefined the .toString() function of the inner function fn! This method will be called by Javascript whenever the function is used without an arguments list and "some value is expected". Technically it is a "hack" as it will not return a string but a number, but it will work in a way that is in most cases the "desired" way. Give it a spin!

    0 讨论(0)
  • 2020-11-27 14:46

    in addition to what's already said, here's a solution with generic currying (based on http://github.com/sstephenson/prototype/blob/master/src/lang/function.js#L180)

    Function.prototype.curry = function() {
        if (!arguments.length) return this;
        var __method = this, args = [].slice.call(arguments, 0);
        return function() {
          return __method.apply(this, [].concat(
            [].slice.call(args, 0),
            [].slice.call(arguments, 0)));
       }
    }
    
    
    add = function(x) {
        return (function (x, y) { return x + y }).curry(x)
    }
    
    console.log(add(2)(3))
    
    0 讨论(0)
提交回复
热议问题