rescript-compiler
rescript-compiler copied to clipboard
Add BigInt primitive number type
I'm surprised no one suggested this yet (the only other relevant issue I could find was #2903). Now that all major browsers and runtimes support it (ignoring IE which is EOL'd anyway), I guess it's about time to add it as a primitive number type.
- BigInt literals
1n
,9007199254740991n
- Conversion from/to strings/ints/floats
- Binary operators and/or built-in functions for arithmetic on bigints, e.g.
+ - * / ** %
(The MDN doc shows a couple static functions too, but they're not yet supported on Safari, and I don't think they're that useful.)
indeed, it's something we should add. note 3n
has a special meaning in ocaml, it's nativeint. Shall we choose a different suffix or just override it.
If we use n
as a suffix, we need check if we can make this works:
let f = function
| 1n
| 2n -> 0
| x -> Nativeint.add x 3n
We don't need a special literal imho. BigInt(1)
is the same as 1n
in JS. It can be done purely with bindings, say, a Js.BigInt
module. Js.BigInt.ofInt
, ofString
, etc., can be constructors.
i feel like special literals would be better (like %re
) so we could transpile to, say, 10000000000000n
nicely
It would make it perhaps slightly more convenient to do e.g. %bigint(10000000000000)
instead of BigInt.ofString("10000000000000")
, I just don't know if it's worth the tradeoff of implementing custom support in the compiler as opposed to just writing a library-level binding.
@yawaramin it would also be possible to avoid having to allocate a string - not that there's a noticeable difference in perforamance very much of the time, but i do believe it'd be slightly more idiomatic? idk
This proposal is sorely needed IMO, we at least need a single type in pervasives for libraries to target to as a first step.
We don't need a special literal imho.
I disagree, literals are much more intuitive and much less error prone. ofString
would have to be used everywhere which is a really frustrating experience when coming from JS.
Another +1 for why this is needed, Temporal will be landing in the coming months and parts of the API rely heavily on bigints: https://tc39.es/proposal-temporal/docs
Compiler support would be great also for output size - BigInt("100000")
vs 100000n
. You could argue that compression negates this point, but that only helps in bundles.
@somebody1234 aren't strings interned by JS runtimes nowadays? And in any case, I doubt that calling the constructor like BigInt("1")
would allocate a string.
@tom-sherman anyone can send a PR for at least initial BigInt bindings even without a custom literal syntax. Just need to create a new module Js.BigInt
, put the t
type and the rest of the bindings in there.
About 'frustrating experience', I'm not really seeing how it's worse than having to use e.g. React.string
etc. ReScript is a little bit more explicit than JS/TS in return for being much more type-safe. and if typing out BigInt.ofString
is a burden, then it's easy to do let b = BigInt.ofString
, which also resolves the output size issue, not that it should be a serious issue in the first place if people are correctly using HTTP compression to deliver JS and other payloads in production settings.
The ofString
function introduces room for runtime errors though, errors that should be caught at compile time. It also requires the developer to be aware of the edge cases of string->bigint conversions, which can lead to very unexpected results. This is mental overhead that can all be avoided with a literal.
@yawaramin interned... sure. whether the runtime would optimize that into a bigint constant... i don't know.
of course as i basically mentioned before, it'd also be more "idiomatic" - as in, in js nobody uses BigInt("string literal")
since bigint literals are a thing. therefore including bigint literals would result in more conventional output.
@tom-sherman OK but the parsing of the literal has to happen somewhere. Making it compile-time in ReScript would mean duplicating the BigInt literal parsing functionality that already exists in the JavaScript platform, making sure to duplicate all its possible quirks and edge cases, and keeping those up-to-date, otherwise when people run into edge cases they will be super confused why ReScript BigInt literal parsing behaviour is different than vanilla JS (small example that we can already see: ReScript parses 1.
as a valid float).
Anyway, whether that's done or not, all I'm saying is that the Js.BigInt
module is needed anyway, and it will be much easier to implement than compile-time BigInt literal parsing. So perhaps some interested party can work on that, at least.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Too eager, stale bot! https://github.com/rescript-lang/rescript-compiler/pull/6670
Resolved #6670