2025-04-07 [09:02:15.0546] I see that there's a Decimal.Amount item on the agenda. Would it be possible to get a reply from sffc or Jesse to [this question](https://github.com/tc39/proposal-measure/issues/26#issuecomment-2759531000) I left on the issue two weeks ago? [09:03:46.0492] yes, I'll take a look -- thanks! 2025-04-09 [07:03:13.0310] if you're interested, you're welcome to take a look at the current slides for the decimal update next week: https://notes.igalia.com/p/tc39-2025-04-decimal-intl-integration#/ [07:04:21.0629] I've tried to incorporate feedback on our recent discussions here and present a version of Decimal.Amount that I think warrants discussion in plenary [07:08:34.0338] eemeli: are you happy with N-ic's response to the question? [08:43:33.0169] I think 1. We should spend more time overall on motivation and less on the API 2. Discuss how this design addresses committee feedback from February 3. We should probably change "withSignificantDigits" to "toAmount" to address Eemeli's feedback) [08:47:21.0619] agree -- I can add a bit to the slides [09:23:02.0933] Thanks! * I think slide 8 would be better if it demonstrated *in*equality of values with differing precision (e.g., `v.equals(v.withFractionalDigits(2)) // false`). * There seems to be a typo on slide 11 (extraneous trailing `)` in the code block). * On slide 12, "_`Intl.NumberFormat` should handle `Decimal.Amount` values (the former is a kind of number)_" seems non-grammatical (what is "_the former_" referring to?). * Slide 15 misspells "Discussion". [09:23:22.0470] ack, thank you -- I'm on it! 2025-04-10 [22:31:05.0129] Niocolo's reply does answer my questions, but it doesn't really make me happy about `Decimal.Amount`. According to the current version of the slides it's described as: > Today, we propose a new `Decimal.Amount` primordial for storing a (1) decimal value (2) with a precision (3) but without a unit. That last part in particular seems rather novel and surprising, and I can't find any mention of such an approach in the repo or meeting notes. I proposed the term "amount" as an alternative for "measure", but now it's being taken up as a part of Decimal and won't include any units? [22:39:36.0205] My mental model of `Decimal.Amount` is that it contains both a precision and a unit [22:41:14.0124] * My mental model of `Decimal.Amount` is that it contains both a precision and a unit. I just looked at Jesse's updated slides and they are proposing a specific shape I haven't seen before. [22:46:40.0126] I don't agree with the framing of the motivation on slide 4. There wasn't consensus that the proposals remain separate; I would describe it as skepticism raised by some delegates that the use cases were similar enough to merge them. [22:50:33.0422] We should highlight that we took home the feedback about building a _protocol_, and we investigated it. We found, however, that only the primordial brings immutability, ergonomics, and interoperability to the table. To address the feedback about a top-level `Amount` not seeming well-motivated, we are coming with an updated proposal that scopes the primordial under `Decimal.Amount`, to make clear that this is a type that is designed to live in the Decimal universe. [23:57:22.0391] why would "amount" include a unit? [23:57:31.0979] amount to me is like a magnitude, it's unitless [00:09:25.0928] > <@ljharb:matrix.org> why would "amount" include a unit? The idea is that: - the decimal proposal introduces plain decimals, exactly as it was for the past year - for good Intl integration and to be able to fully represent external decimal128 values, the proposal also introduced an object that lets you represent a (decimal,precision) pair. This object doesn't support any operations, it's just some data payload + a comparison function. It has a prototype, to put the function on it, as well as things like .toLocaleString. - the measure proposal needs a way to define an (object,precision,unit): given that for the other proposal we are defining (object,precision) already, this proposal can just add the unit there. Whether it's called Amount, Measure, or something else doesn't really matter for now — if we have .to/.with/.someThing else methods to get to it, we could even not expose the constructor at all (like we don't expose ArrayIterator) [00:10:06.0906] * The idea is that: - the decimal proposal introduces plain decimals, exactly as it was for the past year - for good Intl integration and to be able to fully represent external decimal128 values, the proposal also introduced an object that lets you represent a (decimal,precision) pair. This object doesn't support any operations, it's just some data payload + a comparison function. It has a prototype, to put the function on it, as well as things like .toLocaleString. - the measure proposal needs a way to define an (object,precision,unit): given that for the other proposal we are defining (object,precision) already, this proposal can just add the unit there. Whether it's called Amount, Measure, or something else doesn't really matter for now — if we have .to/.with/.someThing else methods to get to it, we could even not expose the constructor at all (like we don't expose ArrayIterator). Although this is more like a nuclear option, because people will give a name to these objects and we are in a position to direct that. [00:10:15.0365] * The idea is that: the decimal proposal introduces plain decimals, exactly as it was for the past year for good Intl integration and to be able to fully represent external decimal128 values, the proposal also introduced an object that lets you represent a (decimal,precision) pair. This object doesn't support any operations, it's just some data payload + a comparison function. It has a prototype, to put the function on it, as well as things like .toLocaleString. the measure proposal needs a way to define an (object,precision,unit): given that for the other proposal we are defining (object,precision) already, this proposal can just add the unit there. Whether it's called Amount, Measure, or something else doesn't really matter for now — if we have .to/.with/.someThing else methods to get to it, we could even not expose the constructor at all (like we don't expose ArrayIterator). Although this is more like a nuclear option, because people will give a name to these objects and we are in a position to direct that. [00:10:38.0824] * The idea is that: - the decimal proposal introduces plain decimals, exactly as it was for the past year - for good Intl integration and to be able to fully represent external decimal128 values, the proposal also introduced an object that lets you represent a (decimal,precision) pair. This object doesn't support any operations, it's just some data payload + a comparison function. It has a prototype, to put the function on it, as well as things like .toLocaleString. - the measure proposal needs a way to define an (object,precision,unit): given that for the other proposal we are defining (object,precision) already, this proposal can just add the unit there. Whether it's called Amount, Measure, or something else doesn't really matter for now — if we have .to/.with/.someThing else methods to get to it, we could even not expose the constructor at all (like we don't expose ArrayIterator). Although this is more like a nuclear option, because people will give a name to these objects and we are in a position to direct that. [00:10:50.0378] Oh well I give up on formatting this as a list [00:12:34.0955] I was proposing that `Decimal.Amount` adds both precision and unit. There is no middle intermediate type; it is just a `Decimal.Amount` with a null unit. Some delegates were already skeptical of adding 1 type, so I didn't want to push my luck with 2 types (and then we'd have to name them), plus Luca pointed out that there isn't really any JS duck-typing advantage to distinguishing "null unit" from "type does not support a unit". So it seems simplest to keep them as one type. [00:13:45.0683] Yes I've been convinced that we should have them as a single object. The .unit should be on the Decimal.Amount object, and not on a third new one. [00:14:10.0429] This is unrelated to how the proposals are merged/split though, a proposal can add a property/field on an existing object [00:15:24.0760] /me verifies that the Decimal.Amount OP does indeed state that the unit is in the data model of Decimal.Amount [00:16:36.0326] I see [00:16:59.0649] Yes I double-checked yesterday too :) My mental model of the end state matches exactly what you described there [00:17:29.0872] If you think removing the unit field from my formulation of `Decimal.Amount` is more likely to make it palatable in the short term for Stage 2 purposes... okay with me. Not sure about Eemeli. [00:19:01.0064] I think it's not only good for decimal (keeping the proposal focused on its goal), but it also makes life easier for proposal-that-adds-the-unit: there is no new object to justify, it's just adding a field on an existing one [00:20:32.0529] And I think Decimal.Amount should be justified entirely on Intl integration and interop with external systems, without saying "it will be _needed_ to add units", even though we must make it clear from the beginning that the plan is the other proposal will slot into that [00:23:58.0413] A question I have for eemeli is: you expressed disappointment with entangling the two proposals in the past. If plain Decimal was much further ahead in the process than Measure (or if decimal was already stage 4!), would you be ok with this design? [00:58:00.0772] I continue to think that trying to intermingle these proposals is making the whole situation less rather than more clear. Is "this design" the following? - A `Decimal` would not carry any precision information. - The decimal proposal introduces `Decimal.Amount` as an object that carries precision information, but does not support mathematical operations. - The measure proposal adds `unit` to `Decimal.Amount`. [01:13:16.0263] Yes [01:34:53.0337] Ok, then in a hypothetical future where something like `Decimal.Amount` was already stage 3 or 4, then it would indeed be obvious for measure to be adding `unit` to it. But this is not where we are now, and I don't see the value of the question. More significantly, I don't understand why `Decimal.Amount` needs to be included in the decimal proposal, if `Decimal` itself will not carry precision information. In the current slides, the motivation and use cases for `Decimal` and `Decimal.Amount` appear to be orthogonal, with the former serving data exchange, while the latter is for formatting values with precision. Why are both of these mixed into the decimal proposal? Would it not be simpler to have one proposal (decimal) providing a solution for data exchange, and another proposal (measure) providing a solution for formatting values with precision? [06:34:05.0076] I think the current `Decimal.Amount` is also relevant for the data exchange story because part of the story may involve a developer's need to preserve all digits of a number coming over the wire, and/or transmitting a decimal value with that precision [06:36:26.0986] with `Decimal` alone, that aspect of the data exchange story is harder to sell because you'd need to store a decimal value from a string coming over the wire, and then calculate the precision of it on the side (e.g. by simple parsing, looking for the "." character, then counting the digits on the left and right). And that extra information would need to stored separately from the decimal value [06:37:42.0077] there is another way to understand the data exchange story, which is preservation of mathematical accuracy (i.e., no rounding). That's where `Decimal` fits the bill [06:58:33.0787] with `Decimal.Amount` we also address complementary needs for formatting decimals [06:59:32.0508] so I understand the point about orthogonal needs but I might say that the current design, with Decimal.Amount, addresses two complementary needs [07:01:21.0880] I think that Decimal.Amount also helps us to not get too entangled with issues of units and the use cases arising from them, such as conversion, formatting, canonicalization (or not?) (e.g. kilometer --> meter) [07:02:32.0354] thus Decimal.Amount helps us to stay in the realm of decimal numbers properly speaking, without getting caught up by unit issues [07:31:23.0383] I'm opposed to making Decimal more complicated by adding this other Decimal.Amount class. What if we made Amount part of the Measure proposal. Whether it's two classes or one, either way could work, but this is beyond the core behavior of Decimal. (It'd be fine if we say, Intl.PluralRules doesn't work for Decimal) [07:31:58.0864] * I'm opposed to making Decimal more complicated by adding this other Decimal.Amount class. What if we made Amount part of the Measure proposal? Whether Amount is a separate class from Measure or it's just a Measure with a null unit, either way could work, but this is beyond the core behavior of Decimal. (It'd be fine if we say, Intl.PluralRules doesn't work for Decimal) [07:33:41.0132] I don't think that "Decimal has no value for Intl" is a reasonable counterargument. TC39 would not let almost any Intl proposal through if every proposal had to be seen as of core importance to every delegate's goals. [07:40:53.0088] so I agree 100% with Eemeli [08:59:10.0955] I'll be a few minutes late [09:03:50.0526] Dan and Eemeli and I are here [09:48:01.0085] Two reasons I don't agree with this line of reasoning: 1. JS is a great language for i18n _because_ we take an Intl-first approach. In the last 10 years, Decimal is second only to Temporal in being a proposal that impacts i18n. It should also take an Intl-first approach. 2. Decimal by itself is a fairly weekly-motivated proposal due to reasons I've made clear on GitHub (we can agree to disagree on this). Decimal with Intl makes the proposal well-motivated. [09:50:54.0192] yes, I disagree with 2 [09:51:28.0050] I'm happy that the Measure proposal is being developed. We should have something like this in our standard library. [09:53:03.0959] but I really don't see any cases where looking at Intl makes us want to go back and change the underlying proposal. I think it'd be worth it to fully develop Measure and check whether there's anything like this. [12:10:33.0513] * What if we made Amount part of the Measure proposal? Whether Amount is a separate class from Measure or it's just a Measure with a null unit, either way could work, but this is beyond the core behavior of Decimal. (It'd be fine if we say, Intl.PluralRules doesn't work for Decimal) [16:44:58.0243] Putting aside disagreements regarding process and procedure, the two _outcomes_ I want to _avoid_ are: 1. JS ends up with separate Decimal and Amount/Measure types that together are not maximally symbiotic 2. JS ends up with Decimal but no intrinsic for its i18n interop The way we get to (1) is if we pursue Amount/Measure by itself, optimized for existing numeric types in JS, and then Decimal comes along later, but Amount/Measure is not designed with maximal Decimal integration. For example, Decimal.Amount has a more elegant way of handling precision than a polymorphic Amount/Measure would be able to have. The way we get to (2) is if Decimal gets to Stage 2 without Intl support, and then Amount/Measure gets blocked for whatever reason (lack of consensus around intrinsic vs protocol, etc). Going back to process/procedure questions, the way to prevent both of these outcomes is to put Decimal.Amount into the Decimal proposal (with precision only, no units for now) and advance it to Stage 2. If Decimal gets approved, so does Decimal.Amount. [16:52:04.0477] It's worth reminding everyone that we _almost_ got Stage 2 on full decimal last summer. The hold-out was Jordan who took the position that "if we're adding Decimal, let's do it right and make equality and arithmetic and stuff work the way devs expect it to work". In other words, the other delegates were mostly okay with having a type in the language that has the shape of Decimal.Amount. Our latest proposal is that we have Decimal as the ergonomic entrypoint, and we keep full decimal, renamed to Decimal.Amount, to cover the use cases that Decimal doesn't cover by itself. This seems like a great compromise. [16:52:20.0492] * It's worth reminding everyone that we _almost_ got Stage 2 on Full Decimal128 last summer. The hold-out was Jordan who took the position that "if we're adding Decimal, let's do it right and make equality and arithmetic and stuff work the way devs expect it to work". In other words, the other delegates were mostly okay with having a type in the language that has the shape of Decimal.Amount. Our latest proposal is that we have Decimal as the ergonomic entrypoint, and we keep full decimal, renamed to Decimal.Amount, to cover the use cases that Decimal doesn't cover by itself. This seems like a great compromise. [16:52:48.0877] * It's worth reminding everyone that we _almost_ got Stage 2 on Full Decimal last summer. The hold-out was Jordan who took the position that "if we're adding Decimal, let's do it right and make equality and arithmetic and stuff work the way devs expect it to work". In other words, the other delegates were mostly okay with having a type in the language that has the shape of Decimal.Amount. Our latest proposal is that we have Decimal as the ergonomic entrypoint, and we keep Full Decimal, renamed to Decimal.Amount, to cover the use cases that Decimal doesn't cover by itself. This seems like a great compromise. [16:56:50.0436] What do people think of this comparison: in Temporal, by themselves, MonthDay or YearMonth might not be super strongly motivated. We would have been able to achieve most of the value proposition of Temporal by just having PlainDate. However, the champions decided amongst themselves that these two types were an important part of the whole overall package of an ergonomic datetime API. The plenary trusted our judgement, and now we have the types. In a similar way, Decimal.Amount should be a type that we position as motivated as a piece of the ergonomic numerics type system, and it is just one piece of the proposal that we put in front of plenary. [16:59:07.0052] * Putting aside disagreements regarding process and procedure, the two _outcomes_ I want to _avoid_ are: 1. JS ends up with separate Decimal and Amount/Measure types that together are not maximally symbiotic 2. JS ends up with Decimal but no ergonomic solution for its i18n interop The way we would get to (1) is if we pursue Amount/Measure by itself, optimized for existing numeric types in JS, and then Decimal comes along later, but Amount/Measure is not designed with maximal Decimal integration. For example, Decimal.Amount has a more elegant way of handling precision than a polymorphic Amount/Measure would be able to have. The way we would get to (2) is if Decimal gets to Stage 2 without Intl support, and then Amount/Measure gets blocked for whatever reason (lack of consensus around intrinsic vs protocol, etc). Going back to process/procedure questions, the way to prevent both of these outcomes is to put Decimal.Amount into the Decimal proposal (with precision only, no units for now) and advance it to Stage 2. If Decimal gets approved, so does Decimal.Amount. 2025-04-11 [17:04:20.0500] * What do people think of this comparison: in Temporal, by themselves, MonthDay or YearMonth might not be super strongly motivated. We would have been able to achieve most of the value proposition of Temporal by just having PlainDate. However, the champions decided amongst themselves that these two types were an important part of the whole overall package of an ergonomic datetime API. The plenary trusted our judgement, and now we have the types. In a similar way, Decimal.Amount should be a type that we position as motivated as a piece of the ergonomic numerics type system, and it is just one piece of the proposal that we put in front of plenary. I don't think it is right to position this as a question we ask plenary: "should we include Decimal.Amount?" That's just an opportunity for inconclusive debate around what it means to be motivated and what is the bar for being motivated and what the alternatives could be. In Temporal, we didn't ask "should we include Temporal.PlainYearMonth?" We just included it as part of our package. Delegates who were interested left feedback on GitHub. This is what we can and should do with Decimal.Amount. [17:05:18.0065] * What do people think of this comparison: in Temporal, by themselves, MonthDay or YearMonth might not be super strongly motivated. We would have been able to achieve most of the value proposition of Temporal by just having PlainDate. However, the champions decided amongst themselves that these two types were an important part of the whole overall package of an ergonomic datetime API. The plenary trusted our judgement, and now we have the types. In a similar way, Decimal.Amount should be a type that we position as motivated as a piece of the ergonomic numerics type system, and it is just one piece of the proposal that we put in front of plenary. I don't think it is right to position this as a question we ask plenary: "should we include Decimal.Amount?" That's just an opportunity for inconclusive debate around what it means to be motivated and what is the bar for being motivated and what the alternatives could be. In Temporal, I don't recall us asking "should we include Temporal.YearMonth?" We just included it as part of our package. Delegates who were interested left feedback on GitHub. This is what we can and should do with Decimal.Amount. [01:09:33.0158] > Decimal but no ergonomic solution for its i18n interop sffc What would this look like? As we've agreed that Decimal (the one that does math) won't include precision, my understanding is that without any changes in ECMA-402 attempting to format a Decimal with NumberFormat or select its plural category will call its `.toString()` method, and get the user the result that they might expect from the Decimal's numerical value. This won't really add any new capabilities for number formatting, but it won't take them away either, so I don't see how the i18n interop of even a minimal Decimal would not have an ergonomic solution. [01:11:46.0694] Also, just to clarify, I am not advocating for a polymorphic Amount, and I'm not aware of anyone else doing so either. I do think that a black-box Amount would be sufficient for i18n purposes, but that's not the same thing. [01:15:43.0703] The "good intl support for decimal" that Shane would be happy with is something along the lines of https://github.com/nicolo-ribaudo/proposal-numeric-with-precision (but just for decimal). It's what evolved in the discussions of merging decimal and measure, but we can figure out what's the _minimal_ chunk that would need to be added to Decimal that: - is good enough for intl - can be extended by the measure/amount proposal [01:17:56.0173] * The "good intl support for decimal" that Shane would be happy with is something along the lines of https://github.com/nicolo-ribaudo/proposal-numeric-with-precision (but just for decimal, and without the protocol). It's what evolved in the discussions of merging decimal and measure, but we can figure out what's the _minimal_ chunk that would need to be added to Decimal that: - is good enough for intl - can be extended by the measure/amount proposal [06:05:24.0806] can you say more about what a black-box Amount is, versus a minimal Amount? [06:06:15.0607] atm the current Decimal.Amount does almost nothing, except string formatting and equality comparison (which itself is pretty trivial) [06:06:23.0649] It's an Amount that doesn't directly tell you what its contained value is, so it's only available as e.g. a string. [06:07:36.0113] ah, I see. At the moment that's what we've got, though the current design needs to be updated somewhat if we want this to be a basis for measure, and not just the end of the road for Decimal [06:22:00.0950] another alternative is that Measure/Amount is its own primordial [06:23:15.0658] we've talked about the 2-class vs. 3-class approach before, and argued in favor of the 2-class approach, but I wonder if we want to revisit that [06:24:33.0850] the line of thinking I have in mind is: is Measure really so close to Decimal.Amount that Measure has to be viewed as an extension of Decimal.Amount? [06:25:42.0537] if we look at Decimal.Amount as a solution to a couple of problems arising from the decimal problem space, then maybe it's just an accident that Measure -- if you drop some data -- looks like a Decimal.Amount [07:39:35.0891] OK, I guess I'm sold on Decimal.Amount at this point [07:39:53.0892] we should probably go back and make sure it has the full IEEE data model though (including negative precision) [07:40:10.0567] it vaguely makes sense to model significant digits (?) [07:40:34.0227] I guess I see little risk of 1., but cannot disagree with you that 2. is a possibility [07:41:10.0110] yes, Temporal is a strong reference point for "let's not worry too much about making too many classes, and make sure we have a clean division of what's logically actually represented, rather than filling in nulls" [07:41:23.0945] except the difference is that Decimal.Amount is much lighter-weight [07:42:13.0389] (what if we called the class Decimal.WithPrecision?) [07:54:11.0014] What if for now we call it `Decimal.ThatObject`, and just name it further ahead during stage 2 once both the proposal are at stage 2? :) [07:54:30.0791] heh Amount is fine for now [07:54:46.0374] anyway I've flipped the polarity of how I feel about this proposal [07:54:57.0136] not sure what I was thinking... [07:55:36.0006] it's nice and minimal [07:57:58.0822] (disclosure :P) I was talking with Dan about this potential minimal version of this: https://nicolo-ribaudo.github.io/proposal-decimal-with-precision/ and https://github.com/nicolo-ribaudo/proposal-decimal-with-precision It's currently broken because I forgot to round, and it has the .with method naming that Eemeli suggested to change, but it could be a good starting point [08:04:56.0650] Is this not satisfied by indicating significant digits with a positive integer number? [08:06:39.0017] well, yeah, that's what IEEE calls it, but this proposal flips the sign bit, but that's fine [08:06:59.0351] I think it's probably more intuitive for positive to mean "more decimal places" [08:15:02.0536] I would prefer `Decimal.ThatObject`, or some other clearly not-final name for the part that is getting packaged into the decimal proposal. The i18n problem/need that it's fulfilling was only accepted by committee as a part of the measure proposal, and the clear intent is for it to be filled out with `unit` and `currency` fields by the measure proposal. [08:17:52.0144] sure, SGTM [08:26:24.0911] Jesse: Regarding this phrase in the slides: > We propose a new Decimal.Amount primordial for storing a (1) decimal value (2) with a precision (3) but without a unit. Would it be perhaps more appropriate to phrase it a bit like this? > We propose a new Decimal.Amount primordial for storing a decimal value with a precision. > If accepted, the measure proposal may add fields to this primoridal to store unit or currency indicators. [11:27:57.0700] Yes, that’s closer to the intention — I’ll change it, thanks! [11:59:45.0137] would we need something like a `.withQuantum` method (name TBD) to expose this kind of capability? It could take a positive or negative integer (negative would be equivalent to `.withFractionalDigitss` with a negated argument) [12:02:38.0116] We should pick just one probably, especially because the word "quantum" is not very well known [13:10:01.0755] yes, "precision" is way more clear than "quantum" [13:30:08.0787] For precision, I think both toFixed and Intl use positive numbers to mean "more digits of precision", so it'd be great to follow that. I don't actually know what the current PR does, or what IEEE does. [13:30:46.0270] I think we should stay within what can be encoded by IEEE, but we can expose it differently. Is the quantum the number of fractional digits or of significant digits? 2025-04-14 [11:32:12.0864] Do you think it would it be backward compatible for Intl to check if the argument to `.format()` has a `.significantDigits` property, rather just checking for the internal slot? [11:32:45.0134] For some delegates it's important to try to not check internal slots other than on the `this` argument, so that the feature does not break with membranes [11:32:57.0119] * Do you think it would it be backward compatible for Intl to check if the argument to `.format()` has a `.significantDigits`/`.unit` property, rather just checking for the internal slot? [11:36:19.0920] while i agree with their motivations i think it's reasonable for static methods to check slots on arguments, altho no precedent has been set [11:55:39.0012] yeah, I think this would make plenty of sense -- maybe we could do it in https://tc39.es/ecma402/2024/#sec-tointlmathematicalvalue for the case ToPrimitive would've thrown an error from no method existing [13:43:08.0266] If we have `.format()` check for properties, then what's the decimal-proposal need for something like `Decimal.Amount` to exist at all? Could a `Decimal.p.toAmount()` return something like ``` { valueOf: () => 42, significantDigits: 3 } [15:45:56.0296] eemeli: I struggle to identify a reason to favor that approach (essentially the protocol approach) instead of returning an intrinsic. An intrinsic gives us immutability, ability to attach methods such as toString and toLocaleString, constructors, brand checking. [15:53:40.0343] * eemeli: An intrinsic gives us immutability, ability to attach methods such as toString and toLocaleString, constructors, brand checking. I don't see why _not_ to return an intrinsic from that method. 2025-04-15 [00:29:14.0917] do we want Amount to support NaN, -0, and infinity? [00:29:50.0547] thinking about measurements or financial quantities, I think you could say that all of those shouldn't be there [00:34:36.0127] we could easily support those since decimal supports them. Intl also supports them, so we'd be on solid ground. But we can nonetheless ask whether amount should support them [00:36:18.0140] if we do support NaN etc. do also want Amount to have predicates like `isNaN` etc. that decimal has, or do we require the user to query the underlying decimal? [01:05:27.0952] > <@jesse:igalia.com> if we do support NaN etc. do also want Amount to have predicates like `isNaN` etc. that decimal has, or do we require the user to query the underlying decimal? I think doing `x.decimal.isNaN()` is fine [01:06:20.0886] Does the IEEE spec allow defining things like "infinity with a precision of 3"? [01:07:25.0404] For -0 I think it makes sense to support it. -0.0 and -0.000 seem to me like different numbers (the first one is less than 0 and more that -0.005, the second one less than 0 and more than -0.0005) [01:11:02.0384] in IEEE there's no precision for NaN or the infinities [01:11:08.0992] but there is precision for -0 [02:18:46.0513] Are example _non-formatting_ use cases for decimal-with-precision available anywhere? I can only find a [wrapper](https://github.com/nicolo-ribaudo/proposal-numeric-with-precision?tab=readme-ov-file#examples) for IEE754 precision propagation in nicolo-ribaudo's proposal-numeric-with-precision, but nothing e.g. within the proposal-decimal repo. I think the _formatting_ case for a decimal-with-precision is quite clear, but if the intent is to not have that as the only reason for something like Decimal.Amount, then I think the we ought to say something a bit more that the presentation's current assertion: > For data exchange, we may need to store exact numeric information we receive (the digits, not just the mathematical value) Is that an actual demonstrated need, or a theoretical one that might exist? [02:39:15.0484] those use cases in N-ic's proposal should be integrated into decimal; much of the thinking there maps over into amount [02:44:18.0997] looking ahead (or sideways?) to the measure proposal, the need to have all digits is more clearly motivated [02:46:14.0591] if one temporarily ignores measure, the need for out-of-the-box round-trippability is a nice invariant [02:48:19.0194] btw "amount" is currently not the best name; I've updated the slides to use a placeholder name [02:48:22.0877] suggestions welcome [02:49:20.0397] we've thrown around a few ideas here but haven't really settled on one [05:38:16.0045] What does this mean? What's the use case here? [05:41:24.0056] something like `Decimal.Something.from(x, 3. "fractionalDigits").toString() === x` for all digit strings `x` with up to 3 decimal digits (where 3 is known out-of-band) [05:43:37.0316] * something like `Decimal.Something.from(x, 3. "fractionalDigits").toString() === x` for all digit strings `x` with 3 fractional digits (where 3 is known out-of-band) [05:44:24.0621] this could be used for e.g. currency, where a number of fractional digits is known in advance [06:07:53.0371] If that's important in particular for currency values, then we ought to be quite explicit about it, as this has significant implications for the `.toString()` output once we start to consider including a `currency` field as a part of proposal-measure. [06:13:34.0528] As in, I think it means that either: 1. `toString()` only encodes the numerical value, 2. we ought to include a parser for a number+currency or number+unit string format, 3. we strongly recommend that anyone with a non-formatting reason to represent a number together with a currency or unit not actually do so, or 4. we reconsider a 3-class solution. Presuming, of course, that we agree that this sort of round-tripping is important. [06:15:56.0284] Hence my question earlier: Is there an actual demonstrated need for non-formatting use cases for decimal-with-precision that is significant enough that we need to account for it in this API design, or do we only strongly care about the formatting use cases? [06:16:37.0303] I'm having trouble following; are we proposing having a parser for Decimal.Amount? [06:17:04.0177] let's follow the decision for Decimal. The counterarguments are the same in both cases. If we're going with it, let's stick with it for Decimal.Amount [06:17:34.0977] the most visible usage of a name is on the title slide; you might want to change that [06:17:39.0376] I don't think we ought to have one, but if we seriously care about round-tripping, then that's something we need ot consider. [06:18:01.0612] my understanding was that the driving motivation was around the formatting use case [06:18:41.0217] That's my understanding as well, but e.g. the slides first mention the non-formatting case. [06:18:42.0471] atm there's no parser for Decimal.Something; using the `.from` static constructor method, the 1st argument is a decimal string, which gets passed to Decimal, which does have a parser [06:19:03.0670] where did the demand for round-tripping come from? [06:19:47.0907] it's mentioned in the issue which kicked off this disucssion: https://github.com/tc39/proposal-measure/issues/26 [06:20:16.0940] it's not the topmost need, but it is there [06:21:56.0418] we can focus on the value Decimal.Something has for i18n -- that's the clearest benefit [06:22:45.0646] hmm, do you have the .equals method? [06:22:57.0010] (I don't really know what the use case is for that) [06:23:28.0282] Hang on, how could we even have round-tripping unless we have a parser that parses something like `'1.20'` as something more than just the decimal value `1.2`? [06:23:31.0665] we had it, but dropped it because the use case wasn't exactly clear, and it becomes easily user-definable if we expose the underlying value and precision [06:23:54.0007] I don't see anything on that thread about round-tripping parsers [06:23:56.0297] let's keep this simple! [06:24:09.0186] as minimal as possible [06:24:23.0499] just because we can vaguely conceive of a use case for something doesn't mean we should have it [06:24:34.0047] And to therefore explicitly not aim to support round-tripping, or other non-formatting use cases for decimal-with-precision. [06:24:56.0877] I guess the `from` method is the parser? [06:26:23.0487] yeah, `.from` is the parser (though I might say that `from` contains the decimal parser) [06:26:38.0784] for `.from`, I have in mind taking 3 arguments, no just 1 (a decimal string) [06:27:40.0466] I could imagine it taking 2 (a decimal string and a "precision mode", indicating either fractional digits or significant digits) [06:27:45.0863] but certainly more than 1 [06:28:34.0834] I continue to prefer not having a `.from` factory method, and using `new Amount(value, options)` where the `value` is parsed as the numerical value and the `options` may initially contain `fractionDigits` or `significantDigits`, and be later extended to also support `unit` and `currency`. [06:30:34.0738] we could certainly go either way -- I'm agnostic about that. I think the idea for a static constructor method came from Temporal. But there, we also have `new`, too [06:31:17.0044] yeah I guess my preference for making this absolutely as minimal as possible is fairly soft [06:31:38.0499] I was just surprised that this was part of it [06:31:57.0359] If `new Decimal(value)` works with numbers, strings, and decimal `value`s, then I would find it quite surprising for the same proposal to advocate a different approach for `Decimal.Something`. [06:34:31.0401] tbh I think we didn't quite have this full discussion for decimal -- values were understood as constructed using `new`, only. There was some discussion of having explicit conversion methods (`toNumber`, `toBigInt`) but IIRC we didn't make a decision about whther to have factory methods. We ended up just stuffing everything into the constructor, taking many possible types of arguments [06:35:14.0890] I might suggest this as a topic for discussion in the next champions call next week [06:36:43.0993] Shane hinted at a broader topic in the last call, namely whether Temporal-style design (especially concerning constructors) is something we want generally, in TC39; but IIRC we didn't apply that thinking to Decimal [06:37:38.0828] MM's question yesterday about membranes and static methods makes me wonder if we should ban the Decimal constructor from taking a Decimal [06:37:52.0947] this is a bit edge case-y but that may come up [06:41:01.0053] If the Decimal constructor can't accept a Decimal value, how should one copy a Decimal instance? Also related: If you construct a Decimal.Something with a Decimal value, is the Decimal.Something value the given instance, or a new instance? This matters in particular because Decimal is a class which may be extended. [06:41:31.0201] one way to copy `x` would be `new Decimal(x.toString()` [06:43:03.0342] for constructing a Decimal.Something from a Decimal `x` I was thinking: `new Decimal.Something(x.toString(), n, "fractionalDigits")` where `n` is something known out-of-bounds, as is `"fractionalDigits"` (the knowledge of how precision to be understood) [06:43:41.0036] you could also do e.g. `new Decimal.Something(x.toFixed(n), n, "fractionalDigits")` or `new Decimal.Something(x.toPrecision(n), n, "significantDigits")` [06:44:41.0924] Huh, and after yesterday: should a Decimal value be a Composite with a custom prototype? If it's not, how else could one use a Decimal as e.g. a Map key? [06:47:30.0925] imo we should try to align Decimal with Composite -- what do we need to add to the prototype? [06:48:36.0979] I think it's premature to align Decimal with Composite [06:48:52.0214] anyway you wouldn't change anything about the prototype, just make it a frozen object [06:49:02.0305] (not frozen prototype but frozen instance) [06:49:20.0289] agree it's early days for the composite discussion [06:50:58.0390] if you're saying Decimal should be a Composite, you're saying one thing should block on the other, and I'm not convinced [06:51:14.0098] One relevant part is that I think we can agree that Decimal.Something is not expected to provide a custom equality. [06:52:08.0872] based on the understading of equality Shane sketched in the issue, I think it's not necessary [06:52:18.0153] but if there's something we've overlooked, I'm happy to hear it [06:52:35.0920] custom? [06:52:37.0438] I'm happy to drop that and keep decimal.something really minimal [06:53:09.0348] there are probably some Intl needs for equality that Shane had in mind that we could dive in to [06:53:29.0846] As in, a built-in way to specifically say if two somethings are equal. [06:54:10.0258] Is there pre-existing discussion on whether a non-primitive Decimal ought to be usable in a Set or as a Map key? [06:54:25.0613] maybe we can just keep this presentatlon slightly ambiguous, and focus on talking about the minimal core, and see if people are up for that? then we can argue about details [06:54:52.0281] sffc: this would be helpful; Waldemar seemed to oppose this particular equality operation strongly [06:55:44.0726] I haven't seen discussion about this. The assumption has always been that it'd be a normal object [06:55:56.0182] OK, so just the equals method. [10:05:20.0097] Note that equality is trivial to do in userland [10:05:55.0946] `x.decimal.equals(y.decimal) && x.significantDigits === y.significantDigits` 2025-04-16 [21:49:55.0296] There's a lot here since I last posted my reply. Most of it relates to topics I've already explained in my GitHub issues including #175 and #181. I think my position on most of the comments here is well-known, and back-and-forth on Matrix is not my communication channel of choice. [21:55:56.0337] * There's a lot here since I last posted my reply. Most of it relates to topics I've already explained in my GitHub issues including #175 and #181. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string.. If there are specific concerns, let's make GitHub issues. Back-and-forth on Matrix is not my communication channel of choice. [21:56:16.0949] * There's a lot here since I last posted my reply. Most of it relates to topics I've already explained in my GitHub issues including #175 and #181. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. Back-and-forth on Matrix is not my communication channel of choice. [21:56:34.0943] * There's a lot here since I last posted my reply. Most of it relates to topics I've already explained in my GitHub issues including #175 and #181. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. Back-and-forth on Matrix is not my communication channel of choice. [21:58:13.0246] * There's a lot here since I last posted my reply. Most of it relates to topics I've already explained in my GitHub issues including #175 and #181. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. Back-and-forth on Matrix is not my communication channel of choice. I like Matrix for things like sharing slides and asking quick questions, but I strongly prefer matters of substance to stick to GitHub. [21:58:49.0530] * There's a lot here since I last posted my reply. Most of it relates to topics I've already explained in my GitHub issues including #175 and #181. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. I like Matrix for things like sharing slides and asking quick questions, but I strongly prefer GitHub for matters of substance. [22:00:01.0781] * There's a lot here since I last posted my reply. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. I've already explained my reasoning in GitHub issues including #175 and #181. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. I like Matrix for things like sharing slides and asking quick questions, but I strongly prefer GitHub for matters of substance. [22:01:06.0384] * There's a lot here since I last posted my reply. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. I've already explained my reasoning in GitHub issues including #175 and #181. I don't see anything in the last 100 comments that changes my logic. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. I like Matrix for things like sharing slides and asking quick questions, but I strongly prefer GitHub for matters of substance. [22:01:35.0781] * There's a lot here since I last posted my reply. I think my position on most of the comments here is well-known. In short, I am in support of a clean immutable data type that supports decimal with precision, possibly with future support for units. All methods operate according to that data model, including equals and to/from string. I've already explained my reasoning in GitHub issues including #175 and #181. I don't see anything in the last 100 Matrix comments that would change my logic. If there are specific questions/suggestions/comments/concerns, let's make GitHub issues. I like Matrix for things like sharing slides and asking quick questions, but I strongly prefer GitHub for matters of substance. [10:50:35.0497] sffc Isn't it 34 significant digits, and not 31? (I'm just reading from wikipedia) [10:51:37.0129] presumably we're taking off a few to deal with those edge cases Waldemar is talking about [10:52:20.0522] I'm not sure what Waldemar meant about rounding mode -- does he want that to be a property of the Decimal.Amount? [10:52:24.0131] thanks [11:26:32.0404] I think what WH meant with rounding was triggered by one of my examples: "converting" 42.56 to "42" or "43" if you impute 2 significant digits to the number [11:26:51.0035] it would be "42" using round-ties-to-even [11:27:21.0424] in the current API, there's no place for speciifying a rounding mode, if needed [11:27:35.0821] by contract, `Decimal.prototype.toPrecision` does allow for specifying a rounding mode [11:27:39.0034] contrast [11:28:28.0083] we could certainyl support that [11:31:16.0024] yeah it's 34, though the exponent gets a bit tricky when dealing with subnormal numbers (*extremely* close to zero) [11:31:37.0073] but the 34 significaitn digits is true for those numbers, too [11:33:00.0467] we could add that as an optional argument to `togetherWithSignificantDigits`, as is the case today with `Decimal.prototype.toPRecision` [11:33:44.0587] but then, yeah, I guess that would need to be stored in the Decimal.Amount value [11:34:23.0813] and pass that to Intl.NF rounding options [11:39:28.0578] My presumption is that we would want the numerical value `42.56` of `new Amount('42.56', { significantDigits: 2 })` to be somehow available. [11:39:42.0507] eem-eli thanks for pointing out to MM that he can solve his number formatting needs, today, even with huge/ultra precise numbers by contructing a digit string and passing that to Intl [11:40:51.0233] ah, interesting - we currently have an accessor for the underlying decimal -- which doesn't change when constructing a Decimal.Something -- so that data is recoverable [11:41:48.0743] Because if it's not available, don't we end up with effectively a black-box Amount, and y'all have pushed back against that quite strongly. [11:45:47.0861] Decimal.Amount should do the rounding stuff ahead of time. That's kind-of the point. `new Amount('42.56', { significantDigits: 2 })` should take a rounding mode. [11:46:45.0359] my thinking is that we store the original value but *present* only the (possibly rounded) value [11:47:25.0488] Actually, are there use cases for Decimal.Amount that would not be served equally well by a numeric string? [11:48:26.0988] #175 [11:49:15.0180] https://github.com/tc39/proposal-decimal/issues/175 [11:51:50.0528] I will try to write up my thoughts on Mark and Waldemar's comments, but tl;dr there seems to be a disconnect between both the facts and the goals of the proposal. [11:53:39.0345] I think we don't need to talk about quanta; I didn't quite understand how that came up, and I when i think about Amount I don't feel the need to reach for the concept of quanta [11:54:25.0507] I mean, maybe as an implementation detail, in some implemenations; but it's not necessary to understand the proposal [11:54:59.0059] I mentioned the word in the context of an optimization Decimal.Amount makes possible and didn't mean for the conversation to rathole on that [11:55:50.0315] right I undersood you as referring to a low-level detail; sad that we got sidetracked [11:56:51.0295] So the problem we're working around is that we presume that changing the output of `new Intl.NF().format('1.0')` would not be web-compatible, yes? Do we have any proof of that? [11:57:37.0782] I hope one of these days we can align on the axiom that "significant digits", "fraction digits", and "trailing zeros" are equivalent and interchangeable concepts after being applied to a decimal number [11:58:12.0562] I agree we can convert between those [11:58:25.0711] If we presume that the number of training zeros can be negative, yes. [11:58:35.0197] * If we presume that the number of trailing zeros can be negative, yes. [11:59:24.0575] I think that's equivalent to "downgrading" the # of significant digits [12:33:20.0032] * My presumption is that we would want the numerical value `42.56` of `new Amount('42.56', { significantDigits: 2 })` to be somehow available. [12:33:31.0939] * So the problem we're working around is that we presume that changing the output of `new Intl.NF().format('1.0')` would not be web-compatible, yes? Do we have any proof of that? [12:35:13.0816] sffc: To represent e.g. `new Amount('42.56', { significantDigits: 2 })` using trailing zeros without losing precision on the original value, we'd need to say something like `trailingZeros: -2`. [12:36:17.0032] Same actually goes for fractional digits. [12:36:38.0013] In my mental model, that thing should _absolute_ "lose precision". `new Amount('42.56', { significantDigits: 2 })` is identically equivalent to `new Amount('43', { significantDigits: 2 })` and `new Amount('43')` [12:36:46.0848] * In my mental model, that thing should _absolutely_ "lose precision". `new Amount('42.56', { significantDigits: 2 })` is identically equivalent to `new Amount('43', { significantDigits: 2 })` and `new Amount('43')` [12:37:46.0190] Here's another way of explaining this type. It is the _intermediate_ value during number formatting, something that the language cannot currently represent. It is the value after rounding and precision have been applied, but before the digits are converted to their numbering system specific representation. [12:38:25.0925] Maybe framing it that way would also help address Mark's concern about why we have this only on Decimal but not on Number [12:38:52.0161] `Number.prototype.toDecimalAmount` could totally be a thing [12:40:25.0970] Calling it "decimal with precision" is maybe misleading. It is a "decimal after precision was applied to it" [12:41:16.0529] Except for how intl. NumberFormat treats its trailing zeros, `(42.56).toPrecision(2)` already does something _really_ close to that. [12:42:06.0935] Hence my earlier question: Are we really sure that we can't fix Intl.NumberFormat? [12:54:31.0142] When I worked on string arguments to `Intl.NumberFormat.prototype.format` a few years ago, I got pushback about "let's please not set precedent for using strings as an intermediate decimal representation" and I got Stage 3 by promising I wouldn't try to use strings in this way. :) [12:56:26.0904] So I'm not opposed to exploring whether we could further improve `Intl.NumberFormat.prototype.format(String)` in a web-compatible way, but that doesn't fix the problem of an actual intermediate type. [12:56:56.0048] * So I'm not opposed to exploring whether we could further improve `Intl.NumberFormat.prototype.format(String)` in a web-compatible way, but that doesn't alleviate the need to have an actual intermediate type. [13:02:36.0654] I don't think I understand the use case for a separate intermediate type if formatting or selecting on a numeric string accounts for the precision in that string representation. [13:19:38.0945] For one, you can't do `decimal.withSignificantDigits(5).withUnit("meter")` [13:21:24.0730] * For one, you wouldn't be able to do `decimal.withSignificantDigits(5).withUnit("meter")` without an upgraded intermediate 2025-04-17 [21:33:56.0407] Correct; we would effectively end up with a "three-class" solution where one of the "classes" is a numeric string, i.e. the solution for representing units or currency codes would be wholly separate. [04:57:25.0517] eemeli: Why would this be better? [05:39:31.0397] littledan: Because we already support numeric strings for `Number()`, `Intl.NumberFormat` & `Intl.PluralRules` input, and we provide utilities like `Number.p.toPrecision` to generate them. It is an existing representation of a numerical value with a precision that's supported in JavaScript. I would much rather we make better use of a thing that already exists than inventing a new thing that's functionally almost exactly the same. [05:47:33.0186] it feels like we're going in circles; we've already discussed why the weak typing of strings makes them not a reliable option [06:19:57.0198] Is this unreliability something that has an impact on the formatting use cases of a number-with-precision? [08:28:50.0272] AFAICS even if we were to patch `Intl.NF.p.format` to handle arbitrary digit strings, and even if that fix were web compatible, it wouldn't address the footgun when mixing NumberFormat and PluralRules [08:32:12.0977] We would want to fix both `Intl.NF.p.format` and `Intl.PluralRules.p.select` to respect the significant digits of strings. (I think this may be a good change to make _anyway_, independent of the Decimal proposal) [08:45:05.0020] yeah, the fact that we were able to make the string change in the first place (it used to cast to Number!) makes me optimistic that this will be web-compatible 2025-04-24 [08:05:04.0410] We've a numerics call in a bit under an hour, yes? [08:09:02.0839] yeah! [08:44:04.0229] Chris de Almeida: can you make me an admin of this channel? Or, to put it bluntly: if I tell you what the channel description should be, could you update it? [08:45:11.0473] try now [08:46:21.0003] is it bad to put the call URL in the channel description or does that leak private info? [09:07:15.0246] I'll join the numerics call soon (meeting conflict)