| 07:59 | <Jesse (🇪🇸)> | the decimal continuatin will be this afternoon (early, not late) |
| 08:42 | <Jesse (🇪🇸)> | here are the continuation topics: |
| 08:48 | <Jesse (🇪🇸)> | not sure what WH has in mind with pi to 72 significant digits; this isn't one of the (many, many) Number values that are exactly representable in base-2 and having > 34 significant (decimal) digits |
| 08:49 | <Jesse (🇪🇸)> | I'd love to hear more about use cases for equals for amounts |
| 08:50 | <Jesse (🇪🇸)> | it got removed not because of any opposition to it, just ignorance of any concrete need |
| 08:50 | <Jesse (🇪🇸)> | (I added it in the latest version of the Decimal polyfil, fwiw) |
| 08:52 | <sffc> | It confounds me how any value type wouldn't have an equals function. As the most basic use case, I would like the ability to store these in a hash set. |
| 08:52 | <Jesse (🇪🇸)> | MM's question at the top ("Why is amount tied to decimal?") might have been answered by N-ic's email |
| 08:53 | <Jesse (🇪🇸)> | but it might also be another form of "why a monomorphic decimal-backed amount instead of a polymorphic one" |
| 08:53 | <nicolo-ribaudo> | I still have to answer again to Mark |
| 08:53 | <Jesse (🇪🇸)> | sgtm -- that's convincing enough |
| 08:54 | <Jesse (🇪🇸)> | for the exponential notation question, I'm not sure if there's any issue. All the examples we listed use decimal digit strings but we intend to support exponential notation, too |
| 08:55 | <sffc> | The Equals function gets a bit more fraught with Polymorphic Amount (are numerically-equal Number, BigInt, and Decimal Amounts .equals to each other?) |
| 08:55 | <Jesse (🇪🇸)> | right |
| 08:56 | <sffc> | I think that instead of Polymorphic Amount, I like your idea of String Amount. Many of the Polymorphic Amount problems go away. |
| 08:56 | <sffc> | So the question should be Decimal Amount or String Amount. |
| 08:56 | <Jesse (🇪🇸)> | a String-backed amount definitely aligns with the main use cases for amount |
| 08:57 | <Jesse (🇪🇸)> | conversion functions (toDecimal, toBigInt, toNumber etc.) might throw but maybe that's not so bad |
| 08:58 | <sffc> | We can discuss that in an issue but I feel like toDecimal could have an options argument that tells it whether to round or throw |
| 09:00 | <nicolo-ribaudo> | If we do string amount, I'd prefer conversions to be cast-like operations, e.g. Decimal(amount) and BigInt(amount) rather than amount.toDecimal() and amount.toBigInt() |
| 09:04 | <Jesse (🇪🇸)> | I think E-emli suggested this approach, too? |
| 09:04 | <eemeli> | I would also prefer something like a "string amount". Provided that its .toString() was a numeric string, then new Decimal(amount), BigInt(amount), and Number(amount) would all work. |
| 09:05 | <Jesse (🇪🇸)> | a String-backed amount also leaves open the possibility of adding new numeric types |
| 09:05 | <sffc> | I don't want to get ahead of ourselves on .toString(); I want it to be able to hold a unit annotation |
| 09:06 | <sffc> | Or some other syntax for rationals |
| 09:06 | <sffc> | "4/3" or "1.50[meter]" might be valid string outputs |
| 09:06 | <sffc> | But not as part of the Decimal proposal |
| 09:07 | <sffc> | We should make it future-proof though |
| 09:08 | <Jesse (🇪🇸)> | the decimal continuation might happen after this talk (!) |
| 09:09 | <eemeli> | As in, before lunch? |
| 09:09 | <Jesse (🇪🇸)> | yes |
| 09:09 | <sffc> | As long as Waldemar and Mark Miller are on the call |
| 09:10 | <Jesse (🇪🇸)> | WH is here but MM isn't (and he might not be here in the early afternoon, either) |
| 09:10 | <Jesse (🇪🇸)> | but there are too many contraints for the late afternoon |
| 09:10 | <Jesse (🇪🇸)> | (that's my understanding from the chairs) |
| 09:10 | <sffc> | We could do a WH continuation now and a MM continuation later (both shorter and therefore easier to fit in) |
| 09:11 | <ryzokuken> | neither expressed a constraint fwiw |
| 09:11 | <ryzokuken> | we have enough constraints explicitly laid out that it feels a bit harder accommodating implicit constraints |
| 09:12 | <sffc> | Based on the queue, it looks like the WH items are most of what's left |
| 09:17 | <sffc> | In preparing my slides for the meetup talk this evening, I'm reminded that I still don't recall us getting an answer on whether "redefine BigInt" is feasible |
| 09:18 | <Jesse (🇪🇸)> | redefine bigint? was that the idea of extending bigint with a new property indicating a decimal point index? |
| 09:19 | <Jesse (🇪🇸)> | IIRC this was an alternative path towards getting "decimal" as a primitive |
| 09:21 | <sffc> | Yes. If we did that, then that would also be the [numeric portion of the] Amount type, since it is a superset of the others. |
| 09:22 | <eemeli> | Re "the Amount type", do you mean the type of the numerical value within Amount? |
| 09:22 | <sffc> | yes |
| 09:22 | <eemeli> | If so, I agree. |
| 09:24 | <Jesse (🇪🇸)> | one question would be the data model -- BigInt is an unlimited data type but Decimal128 has bounds |
| 09:25 | <Jesse (🇪🇸)> | I guess Decimal128 wouldn't be the way to go |
| 09:25 | <Jesse (🇪🇸)> | (for this approach) |
| 09:25 | <eemeli> | Yah. |
| 09:26 | <sffc> | "Modified BigInt" is more like "BigDecimal" which is closer to String than Decimal |
| 09:27 | <Jesse (🇪🇸)> | thinking about arithmetic on these values, it's a sort of back-door rational number (but restricted to values that have finite decimal representations) |
| 09:28 | <Jesse (🇪🇸)> | (btw that is definitley doable, and not slow; I'm not raising a performance concern) |
| 09:28 | <eemeli> | Is there any way in which a string-backed Amount could be distinguished from a bigdecimal-backed Amount by a JS user? |
| 09:29 | <eemeli> | (I don't think there is or should be any difference) |
| 09:30 | <Jesse (🇪🇸)> | to my mind nothing sticks out; they seem basically interchangeable |
| 09:32 | <sffc> | That's mostly correct, yes, except that it may prevent us from supporting rationals where a string like "4/3" could be a thing we support |
| 10:01 | <Jesse (🇪🇸)> | it seems that we're converging toward a String-backed Amount that would support all "numerics" via cast-like operations suggested by Eemeli and Nic |
| 10:01 | <nicolo-ribaudo> | Note that string amount is not a solution to all problems, as we might need to redefine that for example 1e+1 and 1e1 are the same number but different strings |
| 10:02 | <Jesse (🇪🇸)> | right we'd need to settle on normalization here too |
| 10:02 | <Jesse (🇪🇸)> | decimal does that kind of normalization in the sense that it accepts both of those but outputs only the 1st |
| 10:05 | <Richard Gibson> | I can say with extremely high confidence that redefining bigint is not feasible. It is a primitive type with existing well-defined integer-only semantics, e.g. 4n / 3n === 1n. |
| 10:05 | <sffc> | No, I would say that we're converging on this being a feasible alternative, not necessarily converging on the preferred approach |
| 10:07 | <sffc> | Just add a new operator and define / as integer division. I see this as a papercut to be weighed with other pros and cons but not a fatal flaw |
| 10:09 | <Jesse (🇪🇸)> | for storage, it might be a bit odd to have bigints be either an integer or a decimal |
| 10:09 | <Jesse (🇪🇸)> | even if we could smooth out the ergonomics and surface area |
| 10:10 | <sffc> | bigints already require a heap, so I don't think it's much cost |
| 10:10 | <sffc> | In other words, they are already not particularly efficient in their storage. We're making a slightly-inefficient-and-not-widely-used type into a slightly-more-inefficient-but-more-widely-used type |
| 10:15 | <Richard Gibson> | oh, "just" add a new operator? And it's not only that anyway, there's also existing ecosystem use of bigint for alignment with interoperable data models such as Syrup and CBOR, in which arbitrarily-sized integers constitute a distinct type from arbitrary decimal and/or binary fractions |
| 10:17 | <sffc> | Yes, the data model concerns are something worth discussing, the nature of the issues involved there |
| 10:17 | <Richard Gibson> | to be clear: not only do I have high confidence that redefining bigint is not feasible, but furthermore I am personally inclined to oppose any such attempt |
| 11:43 | <sffc> | Jesse (🇪🇸): Should we steer the conversation to one of the questions we need answers from MM |
| 11:43 | <sffc> | Better use of time than NaN |
| 12:18 | <eemeli> | I don't really understand the relevance of the rounding discussions, given that AFAIK the only place where rounding might happen with Amount is when going from a high-precision numeric string to Decimal (if that's what's used as its internal representation). Any Amount-internal fraction/significant digit rounding will presumably happen with respect to the value's internal representation, so all of it will happen consistently. |
| 12:20 | <Jesse (🇪🇸)> | yes, I also didn't quite detect the substantive issue that we were trying to get at in the rounding discussion |
| 12:20 | <Jesse (🇪🇸)> | surely, such things would be a stage 2 concern |
| 12:22 | <Jesse (🇪🇸)> | even Intl, with its huge limits, surely has to handle rounding, when given massive digit strings |
| 12:22 | <eemeli> | I do think that unless we use something like a numeric strings as the internal representation, then a constructor needs to be able to define the rounding mode. Would the currently-proposed .from static method allow for a second argument setting that? |
| 12:23 | <Jesse (🇪🇸)> | we could add a 2nd argument |
| 12:23 | <eemeli> | Do any of the prior-art Temporal .from methods allow for a second argument? |
| 12:24 | <Jesse (🇪🇸)> | IIRC those are all single-argument methods |
| 12:25 | <Jesse (🇪🇸)> | this reminds me of the discussion of whether we should also have a constructor, not just .from |
| 12:25 | <Jesse (🇪🇸)> | the constructor would be like Temporal's, where every argument is needed |
| 12:25 | <Jesse (🇪🇸)> | to totally specify everything, without fallbacks |
| 12:50 | <eemeli> | I would think that the Intl.NumberFormat model of value+options bag matches much better, esp. considering future extension for unit/currency support. |
| 12:54 | <Jesse (🇪🇸)> | procedurally, how should we think about presenting a String-backed Amount? would it continue to be part of the decimal proposal? |
| 12:59 | <eemeli> | I would think that'd be easier done as a separate refactored proposal-measure. |
| 12:59 | <Jesse (🇪🇸)> | (not saying we've totally switched to that approach; at this point, it's an interesting potential alternative. just asking hypothetically) |
| 13:02 | <Jesse (🇪🇸)> | otoh in our current discussions of (Decimal.)Amount, we've had the luxury of not yet worrying about units, the thinking being that Measure will round out the picture |
| 13:03 | <Jesse (🇪🇸)> | iow even a String-based Amount could make sense in the Decimal proposal, because it is indeed a kind of numeric value |
| 13:03 | <Jesse (🇪🇸)> | and it works |
| 13:03 | <Jesse (🇪🇸)> | it's like part 1 of a 2-part movie |
| 13:04 | <Jesse (🇪🇸)> | it does make sense on its own |
| 13:04 | <eemeli> | A minimal non-Decimal Amount could start out with unit and currency as string-valued optional properties, and include special handling in Intl.NumberFormat when an Amount used is used in a .format() call. |
| 13:04 | <Jesse (🇪🇸)> | ah, interesting, good point -- I like the idea of pointing to those bits of Intl as prior art |
| 13:06 | <eemeli> | As we're proposing a single class for handling both currency and unit formatting, we're going to have the potential for .format(amount) throwing no matter what, so gating the supported units at that point rather than in the Amount constructor also makes sense. |
| 13:06 | <eemeli> | And doesn't introduce a dependency in ECMA-262 on the ECMA-402 list of supported units. |
| 14:04 | <sffc> | Procedurally, I wonder if we could get Stage 2 on Decimal and Decimal.Amount, followed by the proposal to extend Decimal.Amount to support dimensions and higher precision |
| 14:04 | <sffc> | (in which case we would rename it from Decimal.Amount to something else, perhaps in a Numerics namespace) |
| 14:06 | <Jesse (🇪🇸)> | this sounds like a reasonable path -- I think the committee understands decimal and decimal.amount fairly well at this point. the motivation for increased limits comes more naturally from a discussion of measurements |
| 14:10 | <eemeli> | Or we could just leave out Decimal.Amount from the Decimal proposal, and introduce Amount separately under the measure proposal. |
| 14:10 | <sffc> | My long-standing position is that I don't support the Decimal proposal without the i18n solution |
| 14:11 | <eemeli> | Would those concerns be potentially resolved if we were to propose a non-Decimal Amount for Stage 2 before proposing Decimal for Stage 2? |
| 14:11 | <sffc> | I could be reasonably happy with String Amount to Stage 2 and Decimal to Stage 2 later |
| 14:12 | <eemeli> | That sounds like a thing that could be done relatively easily from where we are now. |
| 14:13 | <sffc> | except for the fact that we haven't presented String Amount to committee before and don't have a temperature check on it :) |
| 14:13 | <Jesse (🇪🇸)> | if so then I wonder if we need to pivot to |
| 14:15 | <eemeli> | I think the most vocal objections to Decimal.Amount as currently proposed have been from Mark and me, regarding the value limits that Decimal imposes. A string-based Amount would resolve those concerns, so I could well believe it getting through unless wholly new concerns are raised. |
| 14:16 | <eemeli> | And as I discovered with Intl.MessageFormat, asking for Stage 2 might be the only way to surface those. |
| 14:16 | <Jesse (🇪🇸)> | I think it makes some sense to do a String-based amount in decimal (called Amount, not Decimal.Amount) |
| 14:16 | <sffc> | (I think it should be Numerics.Amount and Numerics.Decimal but that can be resolved pre-2.7) |
| 14:17 | <Jesse (🇪🇸)> | it makes sense because the use cases for decimal, especially the i18n ones, need (Numerics.)Amount |
| 14:18 | <eemeli> | I would prefer bare Amount over Numerics.Amount, but I agree that this should not be a stage 2 blocker. |
| 14:19 | <eemeli> | To clarify, I don't dislike Numerics.Amount, but prefer the non-namespaced one. |
| 14:20 | <sffc> | It's not dissimilar to SeededPRNG being better as Random.Seeded but probably only if there are other things in the Random namespace |
| 14:22 | <ljharb> | imo we've made lots of mistakes by not optimistically namespacing things |
| 14:23 | <ljharb> | eventually everything gets something else related to it added |
| 14:29 | <eemeli> | On a separate note, have we considered/discussed whether Amount.p.valueOf() should explicitly throw like Decimal.p.valueOf() does? For the latter I gather it's primarily done to prevent something like d1 + d2 from appearing to work, but I'm not sure that the argument made for Decimal wholly applies to Amount. The ergonomics cost of casts like BigInt(amount) and Number(amount) not working is kinda high. |
| 14:30 | <Jesse (🇪🇸)> | my initial gut reaction would be for valueOf to return a serialized number |
| 14:30 | <Jesse (🇪🇸)> | (without units/currency) |
| 14:31 | <sffc> | we should do what Temporal does, which is to throw on valueOf |
| 14:31 | <eemeli> | That would work for me, certainly. |
| 14:31 | <eemeli> | (my response was to Jesse's suggestion) |
| 14:31 | <sffc> | I'm not in favor of valueOf or toString returning something that is equal if the corresponding Amounts are not equal |
| 14:31 | <eemeli> | Why does Temporal's behaviour here matter for Amount? |
| 14:32 | <Jesse (🇪🇸)> | ah, I meant not exactly the number but the number + precision |
| 14:32 | <Jesse (🇪🇸)> | digit string iow |
| 14:32 | <Jesse (🇪🇸)> | this should satisfy the constraint you have in mind sffc |
| 14:33 | <Jesse (🇪🇸)> | how important are casts in comparison to explicit method calls? |
| 14:34 | <sffc> | Temporal decided to throw on valueOf for a number of well-motivated reasons, which I think also apply here. If valueOf returns a string, then people are going to take amt1 + amt2 and get garbage |
| 14:34 | <Jesse (🇪🇸)> | Number(amount) vs. amount.toNumber() |
| 14:39 | <Jesse (🇪🇸)> | I'm inclined to make valueOf throw, to avoid mixing, following the logic of decimal |
| 14:40 | <Jesse (🇪🇸)> | (I wonder if this thinking was one of the "stop casting things" series of talks by KG?) |
| 14:42 | <Jesse (🇪🇸)> | sorry "stop coercing things" |
| 14:47 | <Jesse (🇪🇸)> | btw I realize this is getting into the weeds but what should we do about (1) NaN, (2) -0, and (3) +/infinity? |
| 14:47 | <Jesse (🇪🇸)> | one argument is that we should support all of them because decimal does, and so does intl |
| 14:48 | <Jesse (🇪🇸)> | another approach would be to ban them, the thinking being that an "amount" is always a finite amount |
| 14:48 | <ljharb> | -0 is a finite amount |
| 14:48 | <Jesse (🇪🇸)> | true |
| 14:48 | <ljharb> | banning nan and infinity tho seems fine to me, as long as it throws for them |
| 14:49 | <Jesse (🇪🇸)> | should we normalize -0 to 0? |
| 14:49 | <ljharb> | i strongly dislike doing that overall (as i'll be talking about in the clamp continuation) |
| 14:49 | <ljharb> | but, tbf, that's probably what most people will want done |
| 14:49 | <Jesse (🇪🇸)> | yeah |
| 14:50 | <Jesse (🇪🇸)> | I'd like us to have Amount(0).equals(Amount(-0)) to be true |
| 14:50 | <Jesse (🇪🇸)> | at a minimum |
| 14:50 | <ljharb> | i also dislike that but i think it's much more defensible given === and the concept of an amount |
| 14:50 | <Jesse (🇪🇸)> | ah ok interesting |
| 14:51 | <ljharb> | like, in general i think IEEE's -0 behavior is confusing and bad and we shouldn't constrain ourselves to something whose importance and impact we've long since surpassed |
| 14:51 | <ljharb> | but waldemar for sure, and others possibly, would not be happy with deviating from ieee 754 |
| 14:51 | <Jesse (🇪🇸)> | right |
| 14:54 | <Jesse (🇪🇸)> | the same line of thinking -- "don't deviate from IEEE 754" -- could also be an argument for supporting NaN and infinity |
| 14:55 | <ljharb> | well, supporting a subset isn't necessarily "deviation" |
| 14:55 | <Jesse (🇪🇸)> | we do have things like Infinity.toPrecision(5) --> "Infinity" |
| 14:55 | <Jesse (🇪🇸)> | (rather than throwing) |
| 14:55 | <eemeli> | I think ensuring that the Amount value was guaranteed to be finite would be a good idea. |
| 14:55 | <ljharb> | sure but that's from the olden days when coercing was the thing |
| 14:56 | <Jesse (🇪🇸)> | the golden olden days |
| 14:56 | <ljharb> | having to account for the special Infinity and NaN strings is gross |
| 14:56 | <Jesse (🇪🇸)> | agree |
| 14:56 | <Jesse (🇪🇸)> | ok it sounds like we have consensus on supporting finite values only, as well as -0 |
| 14:57 | <eemeli> | For the interoperability story, an Amount that was able to represent any finite value would be probably the most valuable approach. |
| 14:58 | <eemeli> | I think -0 should absolutely work as an input value, but normalising it to 0 has precedent in String(-0) === '0'. |
| 14:58 | <Jesse (🇪🇸)> | sgtm |
| 14:59 | <Jesse (🇪🇸)> | seems like a stage 2 concern to me |
| 17:08 | <sffc> | Is it already the case that for two Number-s x and y, that x === y implies String(x) === String(y) ? |
| 17:28 | <eemeli> | Yes. |
| 17:29 | <sffc> | That would align with my expectation, and it's also the case for Temporal types, and it's a large part of why I would like to have that property for Amount, too. |
| 17:29 | <sffc> | (including an Amount containing units.) |
| 17:33 | <eemeli> | Equality of amounts implying equality of their string representations is quite straightforward, but inequality of amounts implying inequality of string representations is not quite so straightforward. |
| 21:40 | <Richard Gibson> | yes, but note that === returns true for distinct values 0 and -0, so that implication only holds because Number::toString also treats those values the same (2. If _x_ is either *+0*𝔽 or *-0*𝔽, return *"0"*.) |