While trying to help a little with [Help needed] ReScriptifying Belt / Js API (sync back docs) - #2 by ryyppy I was shuffling docs of Js.Math
module (Js.Math | ReScript API).
We can see there a few groups of functions working over float
s and int
s arguments that native JS does not distinguish. For example:
unsafe_floor_int
let unsafe_floor_int: float => int
Returns the largest integer less than or equal to the argument. This function may return values not representable by int
, whose range is -2147483648 to 2147483647. This is because, in JavaScript, there are only 64-bit floating point numbers, which can represent integers in the range ±(253-1) exactly. See Math.floor
on MDN.
Js.Math.unsafe_floor_int(3.7) == 3
Js.Math.unsafe_floor_int(3.0) == 3
Js.Math.unsafe_floor_int(-3.7) == -4
Js.Math.unsafe_floor_int(1.0e15) // result is outside range of int datatype
floor_int
let floor_int: float => int
Returns the largest int
less than or equal to the argument; the result is pinned to the range of the int
data type: -2147483648 to 2147483647. See Math.floor
on MDN.
Js.Math.floor_int(3.7) == 3
Js.Math.floor_int(3.0) == 3
Js.Math.floor_int(-3.1) == -4
Js.Math.floor_int(-1.0e15) == -2147483648
Js.Math.floor_int(1.0e15) == 2147483647
floor_float
let floor_float: float => float
Returns the largest integral value less than or equal to the argument. The result is a float
and is not restricted to the int
data type range. See Math.floor
on MDN.
Js.Math.floor_float(3.7) == 3.0
Js.Math.floor_float(3.0) == 3.0
Js.Math.floor_float(-3.1) == -4.0
Js.Math.floor_float(2_150_000_000.3) == 2_150_000_000.0
What is this 2147483647 magic number? Yes it is 232 ÷ 2, that is, a 32-bit integer limit. And int
’s underlying type is the 32-bit integer. Sounds reasonable? At the times when ReasonML could target both JS and metal, the caveat made much sense. But is it still valid for ReScript which targets JS only?
I mean, there’s no such thing as 32-bit integer in JS. Everything is a Number
. Every numerical value is capable to represent an integer in the range ±(253-1) and one must to do some extra work to artificially limit results to ±(231-1). And this isn’t done. For example:
Js.log(Js.Math.unsafe_floor_int(1.0e15 +. 0.5))
works just fine despite the caution in docs, because it gets compiled to:
console.log(Math.floor(1.0e15 + 0.5));
which is fine for any JS engine.
So, given ReScript is targeting JS only and getting rid of OCaml pervasives and built-ins, I wonder, does it make sense to keep all these caveats around 232? Or we’d better make a statement that int
is an integer data type holding a value in range ±(253-1).
Are there any dependencies expecting the 32-bit range still?