-
Notifications
You must be signed in to change notification settings - Fork 2
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
General philosophy and vision #13
Comments
It's great to see this fundamental question being addressed! I think issue #10 is also related: if interchangeability is to be maximized, then putting functions on the My personal take is that there is already so much intentional non-interchangeability [1] that has been decided when BigInts were introduced, that maintaining a clear separation line is more consistent with earlier decisions, and less confusing for JS developers than blurring that line. To illustrate what I see as confusion risk: " Aside from JavaScript-specific spec consistency issues, the argument that floating-point/rational/real math and integer math are fundamentally different also holds a lot of water. Certainly, there is a (comparatively small) set of calculations that both Numbers and BigInts can express, but there are also plenty of examples where they produce different results: pretty much any expression that involves non-integer values, or values beyond a certain "safe" range. To illustrate: [1] There is no precision loss or computational intractability reason why [2] "None of the transcendental functions take BigInt arguments" would be less arbitrary (assuming you're sufficiently well-versed in math to know what a transcendental function is [3]), "most of the transcendental functions don't take BigInts, except [3] Does it have to do with teeth? |
@jakobkummerow: Thank you for the excellent insights. Your point about trying to stick with decisions that have already been made is well taken! Though I think there are a few different conclusions one might draw from that be-consistent-with-the-precedent philosophy:
However, even though I feel that the precedent has been set to overload math operations, that does not mean that we should be maximizing interchangeability. In fact, I might be leaning more towards the second philosophy—but with the caveat that I think we should continue to overload math operations where appropriate. The current BigInt status quo, I feel, is:
But I understand that there are many points of view on what the “current precedent” is, and we should be open to them all. In any case, the point that we should be consistent with current precedent is a good point. Perhaps other TC39 delegates who participated in BigInts’ original design (particularly @littledan, but perhaps also @caiolima, @martinthomson, @sarahghp, @chicoxyzzy, @jmdyck, @bakkot, and otherse) can give some insight into what they feel would be most in keeping with the original design’s precedent. |
See here for some earlier discussion: tc39/proposal-bigint#197 Key quote from @littledan:
|
@jakobkummerow: Great find with that @littledan quote; thank you! That quote embodies a tension between avoiding accidental loss of precision due to interchangeability…and reusing the same operations (which is, in fact, a form of that interchangeability). (I include the If we followed @littledan’s quote there to the letter, then we would not have overloaded To make this balance more explicit, I see a spectrum between “maximizing interoperability” and “no interoperability”.
TC39 designed BigInts and Numbers not to be fully interchangeable, and for good reason. But they did not go all the way—they did not make the fourth choice. I think there are good arguments for the second choice (avoiding BigInt Consistency with previous decisions should be our goal (as eloquently put in #14), but the previous decisions are already striking a fine balance between full interoperability and no interoperability. So it’s kind of tough. Having said that, I agree with @syg’s finding of “completeness” to be a very weak argument (#14 (comment)). I think that instead of “completeness”, we should strike for “consistency”…but how precisely to go about being more consistent will be a bit tricky. My current inclination is to remove |
This is a great issue — thanks for creating the space to discuss, @js-choi. I keep mulling over the bigger points, but there are two things that stand out for me just now:
|
BigInts use the usual operators because the creators/champion(s) of the BigInt proposal strongly believed that that syntax is the most ergonomic way to denote common mathematical operations; in other words they strongly preferred I don't think "interchangeability" was ever a goal behind this syntax decision, just programmer convenience and readability of BigInt-using code. In fact, making all binary operators throw for mixed BigInt/Number operands can be seen as minimizing interchangeability, while preserving the familiar and concise operator syntax. There's no technical reason why For the |
The hypothesis is that that by introducing an "oh no doesn't work on BigInt" point, there is at least an opportunity for reflection and education that would nudge folks down the path of thinking harder about their number representation. @jakobkummerow gave me this compelling example the other day. Suppose |
Since floor and ceil are meaningless operations on things that have no decimal part, not allowing these to take BigInts seems fine with me, and your footgun example is compelling. I don't think that thinking automatically precludes every method, though (and certainly not max/min) |
@syg: This is a great point. It might be specific to I do plan to drop BigInt (I’ll try to figure out if there are similar anti-examples for BigInt-truncating |
The broader point isn't that no Math functions make sense and we shouldn't provide BigInt functionality for them, but that a sufficiently small enough subset does that we might still want to keep them separate. |
The first post in this thread states that "precision loss" is a "strong reason" not to aim for interchangeability. The fact that
|
Yes, that is true. But avoiding precision loss is also a spectrum. @waldemarhorwat pointed out in the August plenary that there is precedent for opt-in truncation in But, anyways, I’d be happy to drop I think that these decisions’ precedents are already on a spectrum between “maximum interchangeability” and “maximum separation”. The trade-offs are finicky. My current concrete plan is to drop, in addition to the already-dropped transcendentals, overloaded |
I think I’ve settled pretty firmly on eschewing both “maximal interchangeability” and “maximal interoperability” in favor of “maximal consistency with precedent”. I’ve edited the explainer with the following:
BigInt
This is a good point. I think, unfortunately, that some amount of developer memorization is inevitable. We’re either going to require developers to:
I think these two approaches are basically equivalent in memorization burden. And both approaches throw TypeErrors when invalid operations are attempted on invalid types. But I think the former approach (type-overloaded math methods with some exceptions) is more consistent with precedence (type-overloaded operations with some exceptions like unary We could take this discussion to #14, too. |
We should keep For example, if you want to compute an arbitrary-precision square root of a BigInt, the truncated square root provides a great first step of the algorithm. You then square the truncated square root, subtract it from the original number, and proceed with the algorithm. For another example, if you want to compute a truncated square root of a BigInt to 2 decimal places, multiply your original BigInt by 10000n, take the truncated square root, and you'll get the answer times 100n. |
Another example: Suppose you want to compute the square root of a BigInt n rounded to the nearest integer instead of truncated. This is how you'd do it:
|
Combining the two examples above, here's how to compute the square root of a BigInt n rounded to nearest to two decimal places:
|
@waldemarhorwat: Thanks warmly for the comments. Some feedback that we’ve gotten from engine implementers like @syg, @codehag, and @jakobkummerow is that they do not find “completion” rationales compelling (this is why Having said that, I suspect that BigInt truncating This is part of why I am soliciting research from the TC39 research incubator group as well as from developer surveys. I would welcome further suggestions regarding applications. (This all falls under the greater general philosophy of now-restricting type overloads to obviously useful use cases. I guess that’s another piece of the philosophy that needs to get documented in the explainer.) |
I'm afraid we're getting into analysis paralysis and design-by-voting rather than picking the simplest option, which is including the Math functions that mathematically make sense. |
Then I suggest you do
That argument cuts both ways:
From that claim, in turn, one could also conclude that it's perfectly fine to leave implementations to user space, especially as long as we know of no use cases. |
For what it’s worth, I would like to gently push back against the notion that And if In addition, as long as we’re assuming that “BigInt |
To be accurate, let's keep the distinction between " |
@jakobkummerow |
@Yaffle I agree that |
And then you'd sometimes get the wrong answer.
Yes, lots of things can be done using Numbers. That doesn't say anything about the cases where you want guaranteed precision and rounding/truncating behavior. I'm not interested in rehashing the debate about the general usefulness of BigInts.
One could reach an incorrect conclusion. I was referring to the amount of code this would take, which is minuscule — smaller than some of the comments on this thread. However, the knowledge required to do it correctly is quite specialized and not accessible to most users. Also, a user-space implementation would not work as well as a built-in one because it would not be able to take advantage of the internal representation. |
I presented a brief update presentation about this issue to the Committee at the October plenary today. I didn’t get any strong pushback over the overall philosophy and vision, although feedback time was but brief. I also am moving discussion about BigInt |
Original post
Spinning this out of #8 (comment) and #9 (comment).
There are two dueling philosophies we could take for this proposal.
“BigInts and Numbers should always be interchangeable by default, unless there’s a strong reason they should not be (like precision loss or computational intractability).
“It’s weird and confusing that they’re not already more interchangeable.”
“BigInts and Numbers should not be interchangeable by default. Floating point and arbitrary-precision integers are fundamentally different. The choice of which to use should be thought through by the programmer.
“We already can’t have most of Math work for BigInts due to intractability [see Drop transcendental functions except log10 and log2 #4], so even if we would like them to be interchangeable by default, that intuition just can’t hold up in practice. We need specific use cases for each one.”
Note that both philosophies would agree to add support for BigInt
sign
,abs
,min
, andmax
: there are clear use cases for all of these. (And if a clear use case appears in the future for certain other functions, then even the second philosophy would agree that we can add it in a future proposal.)The proposal’s philosophy so far has been the first one (so it currently includes
floor
,ceil
, etc. in #8). But the engine implementers have concerns about that, and we’re open to changing it. It would be good to make which philosophy we choose—and why we chose it—explicit.There are also some relevant snippets from the 2021-08 meeting notes; I’ll wait until they’re public before I put them here.
CC: @syg, @yulia, @ljharb, @michaelficarra, @waldemarhorwat, @littledan
Edit (2021-09-17): The current answer is: The philosophy is neither maximizing interchangeability or maximizing separation. We maximize consistency with precedent instead.
The text was updated successfully, but these errors were encountered: