Passing a math operator as a parameter

You can't pass an operator as a parameter, but you can pass a function:

function accumulate(list, accumulator){   // renamed parameter
    var sum = 0;
    for(var i = 0; i < list.length; i++){ // removed deprecated for…each loop
        sum = accumulator(sum, list[i]);
    }
    print(sum);
}

accumulate(list, function(a, b) { return a + b; });

This is pretty close to what the Array.prototype.reduce function does, though not exactly. To mimic the behavior of reduce, you'd have to get the first element from list and use that as the seed for your accumulator, rather than always using 0:

function accumulate(list, accumulator, seed){
    var i = 0, len = list.length;
    var acc = arguments.length > 2 ? seed : list[i++];
    for(; i < len; i++){
        acc = accumulator(acc, list[i]);
    }
    print(acc);
}

This way, you could compute the product of list (your method would always return 0):

accumulate(list, function(a, b) { return a * b; });

Update: If you're developing for newer browsers that support ECMAScript 2015 / ES6 (or using a transpiler like Babel), you can also use 'arrow function' syntax to make your code a bit more compact:

accumulate(list, (a, b) => a * b);

I think you can do that in several different ways, but I would suggest you something like this:

var operatorFunction = {
    '+' : function(x, y) {
        return x + y;
    },
    '-' : function(x, y) {
        return x - y;
    },
    '*' : function(x, y) {
        return x * y;
    }
};

function accumul(list, neutral, operator) {
    var sum = neutral;
    list.forEach(function(item) {
        sum = operatorFunction[operator](sum, item);
    });
    return sum;
}

console.log(accumul([2, 3, 4], 0, '+'));
console.log(accumul([2, 3, 4], 0, '-'));
console.log(accumul([2, 3, 4], 1, '*'));
console.log(accumul([], 0, '+'));
console.log(accumul([], 1, '*'));

In the example above, you just need something like accumul([2, 3, 4], 0, '+'); to call you function. operatorFunction[operator] calls the correspondent operator function.

Running the example in the command line, with node.js, gives:

$ node accumulate.js 
9
-9
24
0
1

This version also work if the array is empty. You can not use list.reduce if the list is empty.


If all the operations you are planning to do are binary operations, then you can do this

var operations = {
    "+" : function (operand1, operand2) {
        return operand1 + operand2;
    },
    "-" : function (operand1, operand2) {
        return operand1 - operand2;
    },
    "*" : function (operand1, operand2) {
        return operand1 * operand2;
    }
};

function accumulate(list, operator) {
    return list.reduce(operations[operator]);
}

console.log(accumulate([1, 2, 3, 4], "+"));     // 10
console.log(accumulate([1, 2, 3, 4], "-"));     // -8
console.log(accumulate([1, 2, 3, 4], "*"));     // 24

Tags:

Javascript