ES proposal: arbitrary precision integers
2ality.com
2ality.com
The 'n' suffix is clumsy as hell.
You can't mix Numbers and Integers? That's crazy.
23n + 2 is a TypeError even though "23" + 2 isn't?
Also I didn't see anything about the internal format of these numbers. Normally this shouldn't be a concern, but could affect memory usage.
Giving this proposal a vote of no confidence, even though the need for arbitrary precision is high.
The former is banned because it's error prone the latter is allowed because of backwards compatibility.
It's arguable. There are at least two schools of thought, and both of them are valid. It just depends what you want to do. If you're using arbitrary precision, you're probably in a situation where it's better to be explicit than to have implicit coercion.
For example, what should happen if you do 23n + 0.5? You can't have 23.5n, since it's not an integer. You could convert it back to a Number, but you can't do that if it's 9007199254740992n + 0.5. It's logical to throw an error, if a bit counterintuitive.
Comparisons on the other hand probably shouldn't throw errors.
You could return 23.5 in the former case, but then you'd no longer have an Integer. You could throw an error in the latter case, but that'd be a lot slower for JIT tracing compilers to execute than simply verifying that the types are the same.
Animats pointed out a potentially more serious issue, which is that you can DoS a program by sending it an arbitrary precision number whose size is gigabytes. But that's true of any arbitrary precision number, not just floats.
This works rather well in Python.
>>> a = 10
>>> b = 1.1
>>> c = a + b
>>> type(a)
<class 'int'>
>>> type(b)
<class 'float'>
>>> type(c)
<class 'float'>Python handles common cases, but it breaks when you push it too far:
>>> 1e100
1e+100
>>> 1e100+0.1
1e+100
>>> 1e100+0.1 == 1e100
True
>>> 9007199254740992 + 0.5
9007199254740992.0
>>> 9007199254740992 + 0.5 == 9007199254740992
True
>>> 9007199254740992 + 0.5 + 1
9007199254740992.0
>>> x = 9007199254740992
>>> y = x
>>> y += 1
>>> x == y
False
>>> x = 9007199254740992 + 0.5
>>> y = x
>>> x += 1
>>> x == y
True
You could argue that handling the common cases is all that's needed, but stuff like this pops up in e.g. writing software rasterizers. It might also be one reason why PyPy can't quite match the speed of native programs, though that's just a guess.>> from decimal import Decimal as D
>> 9007199254740991 + D('0.1')
> Decimal('9007199254740991.1')
I would dare say that even with this approach it would be possible to maintain backward compatibility with smart conversion, although I'm not familiar enough with ES internals to be more decided on that.
It's not, it's the exact opposite. Instead of doing type coercion, enforces strict typing. It's what people have asked for for ages, now they get it.
I can kind of understand the FAQ section about it, since JavaScript in the browser has to be backwards compatible, but are there really that many applications that depend on Integers acting like they do now at such high values that just transforming them into Numbers won't suffice? The only difference would be for bitwise operations, which are primarily used in Node, and you can explicitly document that change in a major version update, unlike in a browser.
Also, nitpick: Why not just call it BigNumber, or at least BigInteger? Integer as the name of an arbitrarily large number is going to be confusing.
Edit: newer Ruby versions treat Bignum and Fixnum as just Integer (since it was mainly an implementation detail), but my argument is still the same.
In current Ruby, "Fixnum" and "Bignum" are legacy-support aliases for the unified "Integer" class.
http://blog.bigbinary.com/2016/11/18/ruby-2-4-unifies-fixnum...
> Integer as the name of an arbitrarily large number is going to be confusing.
"Integer" in mathematics is the name of an class of numbers that is unbounded on both the high and low end; it is using "Integer" as the name of a restricted range that is counterintuitive.
As to your second point, why not just move everything to Number then and if it needs a decimal point, treat it as a floating point value? I argued in the original post that there can't be that many applications that depend on the current implementation, and those that do purposefully can be rewritten.
Edit: Integer -> Number
Well, the language has changed so that they are unified. The underlying implementation may use different representations at different sizes, and presumably CRuby still uses the same internal split that the language exposed externally, at least for now.
> As to your second point, why not just move everything to Integer then?
Because not all numbers are integers, so you still need JS's number type (limited range and precision reals) if you have arbitrary precision integers.
Also i don't think this has anything to do with JSON.
>JSON.stringify(123n)
undefined
I guess their proposal accounted for this by not supporting integers at all. But this could still be possible if you knew a service was coercing a string or similar into an Integer type (using proposed Integer.parseInt).The examples in paragraph 1 are moot. An ID doesn't have to be represented with integers locally (it's probably because the server stores it as 64 bit ints) and a string is perfectly fine here. Furthermore, "financially technology" working with such large numbers in JS? Are you kidding me?
Edit: downvote without an answer to my question? very helpful.
Once you deal with distributed systems, you need some "fat" to prevent duplicate ids from being generated. That's usually done with an N-bit prefix identifying the server plus a time stamp prefix.
https://www.npmjs.com/package/big-integer
:)
The lack of automatic number coercion seems lazy. I would prefer number approximations and warnings. Do any other primatives throw errors for operators instead of performing type coercion?
Yes, Symbols cannot be implicitly converted to strings for example.
Even then implicit conversion to string is special cased for each primitive (you can't call toString on null or undefined, see [0]).
> Why are these new specs getting so error happy?
I believe is called "fail fast, fail loud" principle. Remember Symbols are to be used as unique keys, if you accidentally mixed them with strings you'd lose this uniqueness.
[0]: https://www.ecma-international.org/ecma-262/6.0/#table-12
---
> primitive wrapper functions?
I though that primatives would be unboxed so that their toString method could be called. Apparently not.
The problem is this case:
s[t + ""] vs s[t]
For all types they are the same because as we know in JS all properties (even array indexes) are converted to strings. But not for symbols, if you use symbol as "t" then implicitly calling toString would give you wrong result in first case. As this is clearly different from the rest of JS objects it's better to throw an error rather that silently proceed.> I though that primatives would be unboxed so that their toString method could be called. Apparently not.
It's the other way around. Primitives do not have any properties so to call a method on it they are boxed before call.
An example:
Number.prototype.getBoxed = function () { return this}
var x = 2..getBoxed()
X will be a Number wrapper object, not a primitive.