| 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 |
| 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 |
| 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 |
| 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 |
| 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. |
| 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 |
| 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 |
| 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? |
| 19:50 | <Jesse (TC39 ๐บ๐ธ)> | also wanted to ask that |
| 19:51 | <ljharb> |
|
| 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 |
| 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? |
| 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. |
| 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 |