05:31
<eemeli>

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?

05:39
<sffc>
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.
05:46
<sffc>
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.
05:50
<sffc>
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.
06:57
<ljharb>
why would "amount" include a unit?
06:57
<ljharb>
amount to me is like a magnitude, it's unitless
07:09
<nicolo-ribaudo>
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). 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.

07:10
<nicolo-ribaudo>
Oh well I give up on formatting this as a list
07:12
<sffc>
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.
07:13
<nicolo-ribaudo>
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.
07:14
<nicolo-ribaudo>
This is unrelated to how the proposals are merged/split though, a proposal can add a property/field on an existing object
07:15
sffc
verifies that the Decimal.Amount OP does indeed state that the unit is in the data model of Decimal.Amount
07:16
<sffc>
I see
07:16
<nicolo-ribaudo>
Yes I double-checked yesterday too :) My mental model of the end state matches exactly what you described there
07:17
<sffc>
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.
07:19
<nicolo-ribaudo>
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
07:20
<nicolo-ribaudo>
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
07:23
<nicolo-ribaudo>
A question I have for @eemeli:mozilla.org 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?
07:58
<eemeli>

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.
08:13
<nicolo-ribaudo>
Yes
08:34
<eemeli>

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?

13:34
<Jesse>
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
13:36
<Jesse>
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
13:37
<Jesse>
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
13:58
<Jesse>
with Decimal.Amount we also address complementary needs for formatting decimals
13:59
<Jesse>
so I understand the point about orthogonal needs but I might say that the current design, with Decimal.Amount, addresses two complementary needs
14:01
<Jesse>
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)
14:02
<Jesse>
thus Decimal.Amount helps us to stay in the realm of decimal numbers properly speaking, without getting caught up by unit issues
14:31
<littledan>
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)
14:33
<littledan>
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.
14:40
<littledan>
so I agree 100% with Eemeli
15:59
<nicolo-ribaudo>
I'll be a few minutes late
16:03
<Jesse>
Dan and Eemeli and I are here
16:48
<sffc>

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.
16:50
<littledan>
yes, I disagree with 2
16:51
<littledan>
I'm happy that the Measure proposal is being developed. We should have something like this in our standard library.
16:53
<littledan>
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.
23:44
<sffc>

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.

23:52
<sffc>

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.

23:56
<sffc>
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.