Math.sum(1, 2, 3)

Similar to Math.min or Math.max.

const total = Math.sum(22, 10, 106, -5); // 133
// same as doing
const total = 22 + 10 + 106 - 5;

Use case:

const items = [
  { name: 'a', amount: 2 },
  { name: 'b', amount: 3 }
];
const totalAmount = Math.sum(...items.map(function (item) {
  return item.amount;
})); // 5

Could be called Math.add(). Could also include other similar methods, like Math.subtract(), Math.multiply(), etc.

I think this can once and for all put the loathed .reduce() to bed.

2 Likes

"loathed" is not a universal thing, reduce is great.

Having better abstractions is also great! But arr.reduce((a, b) => a + b) is hardly an onerous task, or an unreadable line of code, and it also avoids questions of "does it work with numbers, bigints, or both?"

I can read it, but I can't tell what it's doing until I get to the very end of the line. Oh, and oops, it throws an error now because arr was empty. That initialValue argument is easily forgotten.

I've had to write functions like these on multiple occasions, and I've often wished they were built-in.

2 Likes

Math.sum(...arr) has the problem that it doesn't work for large arrays, because engines still try to put spread arguments on the stack regardless what the function does with them.

I would prefer an iterator method arr.values().sum(), or possibly a generic reducer/collector protocol1 like arr.values().to(Number.sum)/arr.values().collect(Number.sum). This would equivalently work with BigInt.sum.

1: for a protocol, I would expect the "to" method to be implemented as to(target) { return (target[Symbol.fromIterator] ?? target.from)(this); }, it would e.g. also work with iter.to(Array) or iter.to(Set) etc.