00:08
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
one thing that's unclear to me is what operations FullDecimal (I don't like the name but work with me) should support
00:08
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
should it have comparison?
00:08
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I think we agree that FullDecimal should't do arithmetic
00:08
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
but I wonder if we need comparison(s)
00:09
<nicolo-ribaudo>
If I'm the only one that liked the FullDecimal idea I'm happy to drop it, I just liked having "incrementally more information" on these numeric objects rather than "all or nothing", but I have no concrete use cases. It's more of a language purity thing
00:09
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I'm not opposed to it
00:10
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
that's my only (weak) objection -- no clear use cases, it exists mainly for the purpose of abstract language niceness
00:10
<nicolo-ribaudo>
But yes if we have it, I would expect it to have comparison that also checks the precision
00:10
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
IEEE 754 has a comparison that respects the precision (quantum) but it's really weird
00:11
<sffc>
I don't want FullDecimal to be a focus of the presentation. But we should probably be prepared for some of these questions given that delegates will nitpick about them.
00:11
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
equals and less-than are supposed to work with mathematical value (iow ignore precisiopn)
00:11
<ljharb>
yeah it's very weird to compare precision
00:11
<nicolo-ribaudo>
But what if you explicitly have an object that is "number + precision"... you care about the precision, otherwise you'd just have the number
00:11
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
you can detect that two values are mathematically equal but distinct if you have toString
00:11
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
and equals
00:12
<ljharb>
then they're incomparable
00:12
<sffc>
I think FullDecimal should either do a total comparison or it should not have an equals function
00:13
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
(sorry for this, maybe I should stop since FullDecimal isn't a focus of the presentation)
00:13
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I wonder if we should have a converter from FullDecimal to Decimal
00:14
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
(which of course does have less-than, equals)
00:14
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
this feels very temporal-y to me
00:14
<nicolo-ribaudo>
Yes, if we have the three classes I'd expect you to be able to move up and down the hierarchy
00:14
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
like, comparison just does not exist in FullDecimal. you have to explicitly move to another class to do that
00:18
<sffc>
I renamed it to "DecimalWithPrecision" in the two places it is referenced in the slides
00:19
<ljharb>
what does DecimalWithPrecision add besides just being a place to hold a precision value?
00:20
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
one benefit I can see is that toString might have some good use cases
00:20
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
exposing the extra precision data
00:21
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
though tbh that's kinda what toString already does with (canonicalized) decimals
00:21
<ljharb>
ok so it's a bucket, to contain a decimal, a precision integer, and a toString function?
00:21
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
sorry toFixed
00:21
<ljharb>
because if that's all it is, why not just have a toFixed on Decimal.prototype
00:21
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
it essentially imputes a precision to the numeric value
00:21
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
there is a toFixed
00:21
<ljharb>
[d, precision] โ†’ d.toFixed(precision) when i want the combo?
00:22
<nicolo-ribaudo>
Yes, it's exactly that to have the value and the precision as a single thing rather than having to track them individually in parallel
00:22
<ljharb>
i totally get why that's beneficial, but that is a very very small value prop to add a Whole New Class
00:23
<ljharb>
especially when Object.assign(Object(decimal), { precision }) also covers that
00:23
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I worry a bit about developer confusion, too
00:23
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
(if we had the two decimal classes)
00:23
<ljharb>
nobody should be trying to java-ize JS by Nouning up all the things
00:23
<ljharb>
there needs to be sufficient rationale for stuff
00:23
<nicolo-ribaudo>
Well we even have classes like SetIterator ๐Ÿ˜›
00:23
<ljharb>
yes, and that's absurd
00:24
<sffc>
Do you have a suggestion about how decimal.toFixed(5).withUnit("meter") would work without the intermediate type
00:24
<nicolo-ribaudo>
But I do not necessarily disagree
00:24
<ljharb>
we shouldn't have ever had any of the iterator classes
00:24
<nicolo-ribaudo>
I guess without the intermediate type you'd do decimal.toAmount({ precision, unit })
00:24
<ljharb>
(d) => d.toFixed(5).withUnit("meter")?
00:24
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I might suggest decimal.asMeasure({unit: "meter", precision: 5 })
00:24
<ljharb>
like, it's already a solved problem how to carry multiple values around together (and there's multiple solutions, including an object, an array, a closure, etc)
00:25
<ljharb>
(possibly composite keys one day)
00:25
<ljharb>
the benefit of making a Thing for a thing is when there's lots of incremental value you can gain when you for sure have multiple values associated together
00:25
<sffc>
I don't buy this argument, because then ZonedDateTime and most other Temporal types could just have been objects, too
00:26
<ljharb>
i believe they do pretty extensive validation, which imo is sufficient benefit
00:26
<ljharb>
but "two numeric values" doesn't require much in the way of validation
00:27
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
we need to make sure the numbers are in range ร  la IEEE 754 so there is some validation
00:27
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
it's not just a box of two arbitrary values
00:27
<ljharb>
sure. decimal covers the one tho, so it'd only be the range of valid precisions
00:27
<ljharb>
and since toFixed would do that anywaysโ€ฆ
00:27
<sffc>
My model is that the precision gets "merged" into the Decimal without actually storing it in a separate slot (internally)
00:28
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
ah I think there might be a misunderstanding -- toFixed produces a String
00:28
<ljharb>
what is the data model for that?
00:28
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
not another Decimal
00:28
<ljharb>
right, i get that.
00:28
<nicolo-ribaudo>
I think you are confused maybe
00:28
<nicolo-ribaudo>
Jordan is talking about the FullDecimal?
00:28
<ljharb>
doing math with multiple decimals-with-precision is not a goal, as i understand it
00:28
<ljharb>
so the only point of having a decimal-with-precision is to produce a string. am i mistaken?
00:28
<sffc>
What is the type returned by toFixed? Is it a String?
00:29
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
yes
00:29
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
and it already exists on decimal
00:29
<nicolo-ribaudo>
And we add String.prototype.withUnit?
00:29
<ljharb>
lol it'd be more like, toFixed(5, { unit: 'meter' }) or something, i assume
00:29
<sffc>
ok, I see. Fine with me but I'm surprised ljharb is proposing using a string as a numeric type. :)
00:29
<ljharb>
but unless there's good use cases beyond "render a string" i don't know why we'd want a full Class for it
00:30
<ljharb>
lol, i'm not
00:38
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I can imagine that we could drop (canonicalized) Decimal's toFixed and toPrecision, keeping only toString; these methods would instead create a FullDecimal, not a string
00:39
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
and FullDecimal would have toString, of course; it would read out the exact value + precision
00:39
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
there'd be no way, in this line of thinking, of imputing a precision to a decimal
00:39
<ljharb>
ok but how is that better than me making an arrow function that closes over precision and the value
00:40
<ljharb>
or rather, how is that better enough to justify a Class being added, which is a very costly and big thing
00:40
<sffc>
I quite like a design of decimal.toFixed(5) becoming decimal.withFractionDigits(5).toString() and using the intermediate type
00:40
<sffc>
(but again, let's please not get into the weeds on this in plenary tomorrow. it's a good topic for a champions meeting.)
00:41
<ljharb>
agreed
00:41
<ljharb>
i think that the intermediate type needs a much stronger elevator pitch than "it's slightly more ergononic than an arrow function closing over values", is all
03:07
<littledan>
So what do we want the focus to be tomorrow
03:54
<sffc>
So what do we want the focus to be tomorrow
Surfacing any remaining dissent of the type that would block either feature from advancing to Stage 2. Figuring out which delegates are not convinced of the motivation of either proposal and why.
07:41
<eemeli>
My preferred solution for precision would be for Amount to include a significantDigits field. That class already includes an optional unit or currency indicator that needs to be accounted for by any operations on it. Adding precision to it as a third thing (beyond value + dimension) is a much smaller cost than adding a second thing to Decimal.
07:52
<eemeli>
That also allows for Amount to solve by itself the i18n issues around precision, rather than relying on the committee finding agreement on how and whether to include that within the Decimal proposal work.
08:31
<eemeli>
On API details: Is there any reason why Amount ought to include a secondary constructor like Amount.from()? I think Shane's slide 6 alludes to that, but it's not clear to me why that might be desirable over new Amount() supporting the same inputs as might be proposed for Amount.from().
08:34
<Romulo Cintra>
While Ben is on leave, Jesse will be responsible for working on Measure/Amount/Decimal-related tasks, and the remaining tasks will be distributed among other team members, who can also provide support in other tasks if needed
16:15
<sffc>
Temporal sets precedent for new being strict to the data model and .from taking things that get coerced. But this is a nitpick that the champions should resolve. Doesn't have to do with proposal motivation.
16:16
<sffc>
Amount is proposed as opaque. The exact fields are not normative at stage 2.
16:20
<eemeli>
Sure, but e.g. on your slide 5 (data model) the currency/unit is specifically mentioned, but significantDigits is not.
16:22
<eemeli>
"new being strict to the data model and .from taking things that get coerced" sounds like a language design concept that ought to get explicitly discussed in committee, separately from either Temporal or Amount.
16:28
<nicolo-ribaudo>
Do you think new vs .from needs to be discussed before stage 2?
17:11
<sffc>
eemeli: The purpose of this presentation is to identify issues that could block advancement to Stage 2. Your comments are good things to discuss amongst the champions, but they do not strike me as the type of thing that need to be resolved before Stage 2.
17:17
<sffc>
I am seeking feedback on the shape of the solution being a new type called Amount with semantics that is a wrapper over a numeric type with precision and a unit and extremely limited functionality. I think we are in furious agreement on that.
17:29
<eemeli>
I don't think .from vs. new is a blocking concern; I'm really just pointing out that it ought to be discussed in general, separately from either Temporal or Amount.
17:56
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I'm agnostic on static method vs. constructor
19:02
<littledan>
the protocol-based approach to Amount is interesting -- that hadn't occurred to me before
19:02
<littledan>
would that work?
19:03
<littledan>
just like an options bag with value, unit and precision
19:16
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
thanks sffc for pushing this forward
19:17
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
as N-ic and R-omulo mentioned I'm happy to take over the champion role for measure amount for now
19:17
<nicolo-ribaudo>
(co-)champion!
19:18
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
AFAICS it's not the end of the world for amount to be considered mainly a 402 thing
19:18
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
I expect we can sharpen the use cases and motivation and possibly make it clearer that it could be n 262
19:19
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
my sense is that the options bag approach isn't quite what we want; I think we need to pass amounts around as values of their own and not merely as option bags waiting to be slotted into a function call
19:20
<sffc>
I feel the primordial approach is >> the protocol approach. I've definitely considered it before. It is technically a more narrow solution, but it has problems of its own.
19:20
<ljharb>
(certainly i'd assume that the values would be in internal slots and that Intl would read those)
19:22
<sffc>
I feel like we have headway to get alignment on an Intl-namespace thing (not Intl.NumberFormatOptionsBuilder but rather Intl.Amount)
19:23
<sffc>
And then I feel like we have headway to say that Intl.Amount should be just Amount
19:23
<littledan>
yeah I bet the committee will receive it differently if it's in Intl
19:24
<littledan>
I believe you, and am interested in understanding the problems
19:24
<littledan>
great presentation btw, sffc
19:24
<littledan>
I think this really helped push the discussion forward
19:24
<ljharb>
additional functionality, or additional "non-rendering" use cases would help with that case; and also, userland packages/use cases that aren't solely about i18n would help
19:25
<eemeli>
the protocol-based approach to Amount is interesting -- that hadn't occurred to me before
That's the approach taken in the current proposed text for Intl.MessageFormat.
19:27
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
additional functionality, or additional "non-rendering" use cases would help with that case; and also, userland packages/use cases that aren't solely about i18n would help
I think the clearest use case there is unit conversion
19:27
<sffc>
Are you satisfied enough with the prospect for non-intl functionality being added in the future, such as add/subtract and unit conversion?
19:27
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
arithmetic, too, though I kinda have mixed feelings about that one
19:28
<ljharb>
i'm not sure unit conversion is something that will ever be added; based on comments and my intuition it seems like a massive minefield
19:28
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
That's the approach taken in the current proposed text for Intl.MessageFormat.
would love to hear more about the intersection of MF 2.0 and numbers/decimals/amounts
19:28
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
(that wasn't on my radar)
19:29
<ljharb>
but also you can already do unit conversion and math with amounts, you just need to somewhat hardcode the conversion factors
19:29
<ljharb>
so adding unit conversion is only valuable if it avoids needing to code in the factors, right?
19:30
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
i'm not sure unit conversion is something that will ever be added; based on comments and my intuition it seems like a massive minefield
what's interesting is that the unit conversion thing comes close to one of the (admittedly, secondary/tertiarty) use cases for decimal, which is about scientific computation, or, more coarsely, "moar digits"
19:30
<ljharb>
sure. decimal math i'm sold on
19:30
<eemeli>
would love to hear more about the intersection of MF 2.0 and numbers/decimals/amounts
See e.g. here: https://github.com/unicode-org/message-format-wg/blob/main/spec/functions/number.md#operands-3
19:30
<ljharb>
but the units are only relevant for conversion factors when appropriate, and whether/how the precision matters is insanely complex and varied
19:31
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
here's a simple question that's homework for me: do any of the constants in units.xml for conversion go beyond the limits of IEEE 754?
19:31
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
decimal128 that is
19:32
<eemeli>
Unit conversion depends on having a clear understanding of how math works on Amount values, hence wanting to leave it until later.
19:32
<ljharb>
the value is just a number - math works on it the way math works
19:32
<ljharb>
if it's a decimal then however decimal math works, etc
19:32
<ljharb>
the conversion factor (or conversion capability) is the part that seems hard to me
19:33
<eemeli>
What if it's a numeric string?
19:33
<ljharb>
then you're required to do the conversion before making an Amount anyways, based on the slides i saw?
19:33
<ljharb>
value: number | bigint | Decimal was somewhere i thought
19:33
<ljharb>
Amount doesn't seem like its goal is to handle numeric strings
19:34
<eemeli>
Ah, my version supported new Amount('42').
19:34
<ljharb>
we don't do implicit coercion anymore tho, so i don't think that'd fly
19:34
<ljharb>
but either way the rules for conversion to a numeric type are/will be already decided elsewhere
19:35
<eemeli>
With an opaque Amount, that's inside Intl.NumbetFormat.
19:36
<ljharb>
but in that case the usage is only for string rendering. which means it's decidedly not generic and shouldn't be a 262 feature, which doesn't seem like the goal
19:46
<eemeli>
My version of an opaque Amount would include a toString() returning a representation of the otherwise inaccessible value. It's intended to: 1. solve i18n/L10n bugs, 2. provide a way to represent (but not operate on) numeric values beyond number, 3. not conflict with anything that we might want to do with Decimal, and 4. support later proposals for e.g. operations like conversion and Decimal integration.
19:47
<ljharb>
how would that representation be 402-agnostic?
19:48
<littledan>
do we want to do that as part of this, or should it be part of stable formatting?
19:48
<littledan>
are you putting it here as a hedge against stable formatting?
19:50
<eemeli>
@littledan:matrix.org: Could you clarify? I don't really see the link with Stable Formatting.
19:50
<eemeli>
how would that representation be 402-agnostic?
What does that mean?
19:50
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
also wanted to ask that
19:51
<ljharb>

toString() returning a representation โ€ฆ solve i18n/L10n bugs

19:51
<ljharb>
if it's using 402 algorithms to produce that representation, and it's in 262, then it'd have to be toLocaleString, wouldn't it?
19:53
<eemeli>
I updated the gist again to show an opaque Amount, with a toString() method to get at a string representation of the value:
https://gist.github.com/eemeli/0bd413d2f711cbd6016673af8d68c38c
@ljharb:matrix.org: This is the "It" I'm describing above.
19:53
<ljharb>
ok, and how does this differ from Intl.NumberFormat now, with an options bag?
19:54
<littledan>
Rather than having toString, wouldn't toLocaleString('zxx') accomplish the same things?
19:54
<eemeli>
It allows for the value+dimension+precision to be encapsulated.
19:55
<eemeli>
Rather than having toString, wouldn't toLocaleString('zxx') accomplish the same things?
No, because the toString() would only include the numerical value.
19:55
<ljharb>
so does a closure. i don't think that's sufficient motivation to add something to the language
19:57
<eemeli>
You mean like toLocaleString()? That requires re-creating the formatter on every call.
20:00
<Jesse (TC39 ๐Ÿ‡บ๐Ÿ‡ธ)>
No, because the toString() would only include the numerical value.
I guess we omit the unit for pluralization reasons?
20:04
<eemeli>
Mostly it's to provide _some_ access to the opaque value, and to not duplicate the value available from toLocaleString('zxx').
20:05
<eemeli>
I would be very happy to iterate on the designs of an appropriate opaque Amount.
20:05
<eemeli>
It should really be a very small proposal.
20:13
<ljharb>
"re-creating the formatter", why is that expensive?
21:40
<sffc>
toLocaleString is a good on-ramp to i18n. It is often performant, and ICU4X can make it more performant, but the explicit Intl formatters are an option when benchmarks show it to be worthwhile.
21:41
<ljharb>
tbh the formatter design also seems like it doesn't belong as a class, but rather just as a function, but obv that ship has sailed