Real world values are still typed.
"If you need more control ... metadata is your friend."
aka implicit user typedefs. Explicit is better.
These are all integers. There only needs to be one integer type for all of: 0 6 -6 8000000000000000000000. Python gets this right.
Or you can go the JSON route, mumble your way through the numbers spec, let every language do its own thing, and tell the handful of people seriously interested in moving integers too large to be precisely specified by a 64-bit float to encode as strings or something and stop worrying everyone else with the complexity....
I don't follow this one. If your language, static or otherwise, is capable of turning this JSON:
"100"
into a string, and this: 100
into a number of whatever type, then it's also capable of turning this hypothetical input: 100
into one type of integer, and this: 100000000000000000000000000000000000000000000000000000000
into another type of integer.OTOH, exact decimals (of which integers are a subset) differ fundamentally in meaning from limited precision binary (or decimal, though that's more rarely encountered) floating point approximations. Which matters in interchange as well as schema.
{ "int": 1, "float": 1.0 }
Of course it's up to the parser implementation to interpret 1.0 as a float.
The spec is very relaxed about the number type:
JSON.parse('[9223372036854775805]')[0] === JSON.parse('[9223372036854775806]')[0]
You should get: <- true
Is chrome's implementation broken? Those are both numbers that a signed int64 can store precisely but a double float cannot.Postgres is the only popular system with built-in JSON functionality that I know of to correctly round-trip JSON numeric data. Python comes close but fails for any number with a decimal point or in E-notation.
One can argue that the JSON spec is too permissive (and I would disagree, though I'm somewhat a purist). Or a pedant could note that the JSON spec doesn't actually say whether any of the digits in a number are considered to carry information (and does in fact note that many parsers are faulty). But it's unfortunately true that most popular JSON parsers fail to round-trip valid JSON data due to flawed design.
[1] http://json.org/
RFC 7159 not only specifies that all of the digits carry information, it specified exactly what information they carry.
However, it also expressly permits implementations to limit the range and precision of numbers accepted, recommending (but not requiring) range and precision at least equivalent to IEEE 754 float64 be supported.
Can you quote? I don't see where it does, except by reference to common knowledge.
But I should clarify. There are several inefficiencies in JSON numeric representation which may or may not be considered significant by an application. The ones I can think of, in order from "obviously not" to "well, maybe":
1. the case of "e" vs. "E"
2. the optional "+" sign after "e" or "E"
3. presence/absence of decimal point and/or E-notation (shouldn't make a difference, but does in many parsers, such as Python's)
4. the value of the exponent itself (e.g. 3.14 vs. 314e-2)
5. "-" sign in front of any number with a value of 0 (IEEE floats and ones-complement integers do have a negative zero)
6. excess trailing 0 digits after the decimal place (may be used to represent significant figures in scientific applications)
7. digits of lesser significance (obviously the most contentious)
JavaScript ignores all but #5. Python ignores all but #3, and due to #3, sometimes #5 and #7. PostgreSQL `json` ignores none; `jsonb` ignores all but #6 and #7. Personally I would draw the line between #4 and #5. But neither the RFC nor the ECMA spec tell us.
Chrome’s implementation is fine (within spec) and makes the natural choice for a general purpose JSON implementation for JS.
Javascript, for example, has this problem because everything is just a "number" and the number data type is a IEEE-754 double precision float. A double precision float can't represent all int64 values, so transmitting an int64 via JSON to Javascript and using the standard JSON parser is lossy. You could say that Javascript screwed up by making number have a specific precision, and you might be right. Python, for example, gives you seamless arbitrary precision arithmetic.
But the decision to use an arbitrary precision type for all numbers in every language is definitely not appropriate. Arbitrary precision has trade offs, and sometimes it's important to work with machine integers.
"Deep embedding" of JSON data into the host language is the cause of this issue. Recognition that JSON is a separate data type and does not always have an obvious encoding in the native language (including JSON arrays, objects, and null, even if they look like native arrays, objects, and null when you squint at them) is key.
The only widespread JSON implementation I know of to get this right is Postgres's: JSON values live as the "json" or "jsonb" type until you explicitly convert them. No data loss is incurred, with the exception that "jsonb" normalizes E-notation, conflates 0 and -0, drops duplicate object keys, and normalizes their order. Even numeric significant 0 digits are preserved.
(one of my favorite things about Perl 6 is that non-integer literals are rationals by default; floating-point is only used if the literal is specified in scientific notation)