# Passing a math operator as a parameter

I'd like to write a function in Javascript that allows me to pass in a mathematical operator and a list of ints and for each item in that list, apply the operator to it.

Thinking of it in terms of a sum, this is what I've come up with:

``````function accumulate(list, operator){
var sum = 0;
for each(var item in list){
sum = accumulator(sum, item);
}
print(sum);
}
``````

Testing this code produces the following error:

``````var list = new Array();
list[0] = 1;
list[1] = 2;
list[2] = 3;
``````
``````js> accumulate(list, +);
js: "<stdin>", line 9: syntax error
js: accumulate(list, +);
js: ..................^
js: "<stdin>", line 9: Compilation produced 1 syntax errors.
``````

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);
``````

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
``````

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 you often use operators and need to `reduce` the results (`accumulate`), it is highly recommended to develop different helpers, so you can quickly use any input form to obtain the results.

Although, this will not be always the case when you use `reduce`, the following helper will allow to pass the first element of your array as `default` value:

``````reducer = (list, func) => list.slice(1).reduce(func, list.slice(0, 1).pop())
``````

The above, still has a `function` dependency, so you still need to declare the specific function that wraps your target `operator`:

``````sum = list => reducer(list, (a, b) => a + b)
sum([1, 2, 3, 4, 5])
``````

You could then redefine `sum`, for example, as per new input formats you see will be backwards compatible. In this example by using a new helper, `flat` (still experimental as per now; added the code):

``````flat = (e) => Array.isArray(e) ? [].concat.apply([], e.map(flat)) : e

sum = (...list)  => reducer(flat(list), (a, b) => a + b)
mult = (...list) => reducer(flat(list), (a, b) => a * b)

sum([1, 2, 3, 4, 5])
sum(1, 2, 3, 4, 5)

mult([1, 2, 3, 4, 5])
mult(1, 2, 3, 4, 5)
``````

Then you can use `reducer` (or any variant you may find more useful) to simplify the definition of other helpers as well. Just one last example with matrix custom operators (in this case, they are `functions`):

``````zip  = (...lists) => lists[0].map((_l, i) => lists.map(list => list[i]))
dot_product = (a, b) => sum(zip(a, b).map(x => mult(x)))

mx_transpose = (mx) => zip.apply([], mx)
// the operator
mx_product = (m1, m2) =>
m1.map(row => mx_transpose(m2).map(
col => dot_product(row, col) ))
// the reducer
mx_multiply = (...mxs) => reducer(mxs, (done, mx) => mx_product(done, mx))

A = [[2, 3, 4],
[1, 0, 0]]
B = [[0, 1000],
[1,  100],
[0,   10]]
C = [[2,   0],
[0, 0.1]]

JSON.stringify(AB   = mx_product (A,  B))
JSON.stringify(ABC  = mx_product (AB, C))
JSON.stringify(ABC2 = mx_multiply(A, B, C))
``````

just pass 1 or -1 as input then multiply all items with this after wh.

Unfortunately, its not really possible to do this like you are trying to do. What I would do is pass in a number, and have a if/then or a switch/case to decide what to do based on that number