-
Notifications
You must be signed in to change notification settings - Fork 448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Introducing the Bigint #6525
Comments
Looking great! But I don't think the arithmetic operators can overlap with the regular int ones...? cc @cristianoc |
may related with #6477 and https://forum.rescript-lang.org/t/new-operator-for-bigint-support/3922 |
Can't we just open the BigInt module for this? |
How do you mean? |
Yes, we can define new operator for the bigint, we can talk about in this thread. At the same time, I'm going to try to implement to make it using same operator with int, wonder how it looks. |
If I understand correctly, @tsnobip meant that |
I just meant that the regular We can also define a special syntax for the big int operators, like |
Similar to @cometkim suggestion, I'm wondering why the comparison operator only checks if the two arguments are the same type, and the arithmetic operator should be split between integer and float. Maybe it's for compiler efficiency, but why not just check if the two arguments are the same type like the comparison operator? |
Ocaml assigns types based on function usage. You need types assigned for certain optimizations. You couldn't have a compilation unit that exports a polymorphic function and expect it to work on BigInts, Floats, and Ints. For example, compare the output of the two functions: module Int = {
external \"+": ('a, 'a) => 'a = "%addint"
external \"-": ('a, 'a) => 'a = "%subint"
external \"*": ('a, 'a) => 'a = "%mulint"
external \"/": ('a, 'a) => 'a = "%divint"
let add1 = (x) => x + (x / x)
}
module Float = {
external \"+": ('a, 'a) => 'a = "%addfloat"
external \"-": ('a, 'a) => 'a = "%subfloat"
external \"*": ('a, 'a) => 'a = "%mulfloat"
external \"/": ('a, 'a) => 'a = "%divfloat"
let add1 = (x) => x + (x / x)
} If you look at the source of polymorphic comparisons, it is much more complex. If you need performance, you should avoid using it. |
@CarlOlson Yes, indeed. The typechecking logics are quite complex than I expect 😄 let d = 1 + 1
let e = 1n + 1n
let f = 1.0 + 1.0
let g = "a" + "a" // should be type error
let h =
{
() => 1
}() + 1 |
I'm thinking it's a choice between adding another operator for bigint and changing the operators to a polymorphic type, what do you guys think? |
You could actually even keep it for strings, so it's like JS. But I wouldn't trade any performance for this! If it has an impact, then adding operators for big ints would feel natural. |
I think the JS output maybe look okay, but looks weird in syntax layer. we have string concatenation |
It's not that simple. It's what the rest of the world calls type classes (or extensions), and OCaml has been evaluating it for a decade (modular implicit). What I proposed in #6477 is a much simpler solution and is how already done in F# |
This is absolutely necessary. The polymorphic |
Let's stick to a new set of custom operators then? For the syntax itself, I have 0 inspiration, I'd say |
Is there inspiration for the |
Nothing precise, just the fact that we need some character that is not already a math operator (
The issue is that it'd be a first combination of a alphabet letter with a mathematical symbol and it would break the fact that symbols don't need to be surrounded with spaces: let m = 2
let n = 1
let res = m+n
// this is equivalent to
// let res = m + n
// what would happen now? |
Or, we can introduce only the obvious parts, such as type, literals, and untagged variants, and leave operators only in std modules as suggested in #6477 (comment). BigInt is usually used in isolated routines because it doesn't support polymorphic operations |
a backlink to an old discussion #4677 |
I personally don't like addition of custom operators (
|
In my product, all DB IDs are treated as bigint (bigserial). protobuf-js also relies on bigint (fallback to long.js) and I actually stopped using ReScript when developing a similar codec because of missing bigint support. bigint is much more common and has already achieved over 96% compatibility according to caniuse data. Even the recent version of XCode has started to end support for iOS 14 and lower. (There is no emulator...) |
We do need the bigint for AOC 2024! (just kidding 😄) |
I think explicitly opening the I'd rather do that than figure out which flavor-of-the-day operator I need to use for this type. |
But you can already use BigInt with rescript-core |
|
IMHO, there are a lot of advantages to having it as a primitive type, and if we're stuck with the discussion of opening up the Bigint module instead of having it as a primitive type, it would be nice to have reasons why it's worse to have it as a primitive type. |
I have nothing against of having it as primitive type |
We'll need to have represented as a primitive in the compiler anyway for it to work with untagged variants etc. |
If we decide to go with primitive types, I think the debate is split between adding new operators and making the arithmetic operators polymorphic. Adding new operators is simpler than the latter. I'll try to prepare a PR for a poc to make the arithmetic operators polymorphic soon, and it would be nice to see the implementation and performance and continue the discussion. |
I think we could combine having it a a primitive type in the compiler and having you |
It's nice to be able to do it in stages and not be radical. When you say open Bigint, do you mean that the arithmetic operators are the same as int? |
If so, we still need to define the operator for bigint in case of not opening Bigint as default. |
why not just use |
FWIW you can already do that. Many people have been using their own BigInt libraries for years. The easiest way is to bind those functions to raw JS. |
Resolved #6670 |
Introduce unified operators, the ad-hoc specialization for primitive operators. For example adding two values, we have `+` for ints, `+.` for floats, and `++` for strings. That is because we don't allow implicit conversion or overloading for operations. It is a fundamental property of the ReScript language, but it is far from the best DX we can think of, and it became a problem when new primitives like bigint were introduced. See discussion: #6525 Unified ops mitigate the problem by adding ad-hoc translation rules on applications of the core built-in operators which have a form of binary ('a -> 'a -> 'a) or unary ('a -> 'a) Translation rules should be applied in its application, in both type-level and IR(lambda)-level. The rules: 1. If the lhs type is a primitive type, unify the rhs and the result type to the lhs type. 2. If the lhs type is not a primitive type but the rhs type is, unify lhs and the result type to the rhs type. 3. If both lhs type and rhs type is not a primitive type, unify the whole types to the int. Since these are simple ad-hoc translations for primitive applications, we cannot use the result type defined in other contexts. So falling back to int type is the simplest behavior that ensures backward compatibility. You can find related definitions on `ml/unified_ops.ml` file. The actual implementation of translation is colocated into other modules. - Type-level : `ml/typecore.ml` - IR-level : `ml/translcore.ml` You can find it with the function name `translate_unified_ops` Resolved #6477
Propose the Bigint in JS as a built-in type.
mdn: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/BigInt
Background
BigInt
is a new primitive that provides a way to represent whole numbers larger than 2^53, which is the largest number Javascript can reliably represent with the Number primitive. It is not introduced yet to ReScript yet.Proposal
Literal
nativeint
is actually locked in ReScript. I'd like to suggest using the'n'
suffix for the bigint literal.1n
Operators
Basically mostly same to the integer operators.
The text was updated successfully, but these errors were encountered: