Open bakkot opened 2 years ago
Number.sum/BigInt.sum is far less weird than Math.sum/Math.bigSum, but it's pretty unfortunate we can't just have a single Math.sum that works with both.
Number.sum/BigInt.sum is far less weird than Math.sum/Math.bigSum
How so? There's several other Math operations which will remain Number-only (sin
, for example), and the "bigX" naming convention is already established with Uint32Array
/BigUint64Array
.
And the overwhelming majority case is summing a list of Numbers; it would be a shame if users in the common case all had to remember that sum
was in a different place than max
and sqrt
and so on just because sum
can't take BigInts.
"BigUint" is both close to the full "BigInt", and also being a Typed Array means it's already sufficiently weird so as not to be an automatic precedent or convention.
While I agree that would be a shame, I think sadly that's somewhat an unavoidable consequence of the committee's decision to minimize the ability to mix Numbers and BigInts - for example, Math.sum([1, 2n])
should work just fine, and it's a shame it can't, but previously asserted constraints (some of which are yours, iirc) would likely prevent that from being a reality.
I think sadly that's somewhat an unavoidable consequence of the committee's decision to minimize the ability to mix Numbers and BigInts
Well, no, it's completely avoidable: Math.sum
could work with numbers, and Math.bigSum
could work with BigInts. And then the common case would be in the place users would expect it to be. Consequence avoided.
right, but "bigSum" would imply "big sums" to me, not "sums of bigints", which is why i find that naming weird.
I'd be fine with Math.bigintSum
or Math.sumBigInts
or something if that's the main concern. Or having Math.sum()
and BigInt.sum()
, for that matter. It's only really having Math.sum()
which works on numbers which I'm attached to.
My vote is for BigInt.sum()
; I've long thought that putting BigInt stuff onto BigInt.*
is the cleanest way to organize things, and I see the point raised here as confirmation of this preference.
In my view, the mixed-type .max(0, 0n)
example discussed elsewhere is somewhat related to .sum([1, 2n])
. If we simply had non-mixed-type Math.max(0, 0)
and BigInt.max(0n, 0n)
then there'd be no problem, and we wouldn't need to debate which mental model among "prefer first", "prefer last", "prefer Number", "prefer same order for min
and max
", "prefer opposite order for min
and max
", "prefer however I happened to implement .reduce((a, b) => ...)
last time I needed it" etc is most intuitive.
In fact, one could argue that the unresolvable ambiguity of .sum([])
applies just the same to .max(...[])
: if you have BigInt-processing code that wants to do something with the maximum of a potentially-empty list, e.g. increment it, then 1n + Math.max(...list)
will throw a TypeError
if list === []
.
I'm thinking about adding two new methods for doing sum/product. They'd take iterables of numbers:
Math.sum([1, 2, 3]) === 6
.And of course if you pass
Math.sum
an empty array, you'd get0
out. But then these methods can't really work with BigInts at all: you can't distinguish "an empty array of Numbers" from "an empty array of BigInts", so you can't tell whether0
or0n
is the identity. And you can't reasonably haveMath.sum([1n])
give1n
but also haveMath.sum([])
give 0.So I'm thinking there should be separate
Math.sum
/Math.bigSum
methods, each of which only accepts values of one specific type.If committee agrees with that analysis, maybe that informs the design of this proposal? Everything currently in this proposal can get away with polymorphism, but that's not going to be true for every possible method, so maybe it will make more sense to split methods into Number/BigInt versions even when we could theoretically combine them. (see also https://github.com/tc39/proposal-bigint-math/issues/14)
Alternatively, I suppose, we could have
Number.sum
andBigInt.sum
. That would be pretty weird but it would at least avoid this tension.