tc39 / proposal-extended-numeric-literals

Extensible numeric literals for JavaScript
https://tc39.github.io/proposal-extended-numeric-literals/
72 stars 18 forks source link

Passing arguments to numeric template? #23

Open miyaokamarina opened 5 years ago

miyaokamarina commented 5 years ago

E.g.:

decorator @dimension (unit = 'px') {
  @numericTemplate(({ number }) => new Dimension(number, unit);
}

const cm = 42@dimension('cm'); // cm instanceof Dimension && cm.unit === 'cm'
const px = 42@dimension;       // px instanceof Dimension && px.unit === 'px'

That’s also possible to create such constructs in another fashion, but it cannot have default parameters:

decorator @dimension {
  @numericTemplate(({ number }) => unit => new Dimension(number, unit));
}

const cm = 42@dimension('cm'); // cm instanceof Dimension && cm.unit === 'cm'
const px = 42@dimension;     // !(px instanceof Dimension)
littledan commented 5 years ago

We could enable this; I was thinking about omitting the feature, though. Could you explain a little more about your use cases?

miyaokamarina commented 5 years ago

I think, omitting this feature will lead to inconsistency with other decorators flavors (and with tagged templates). Both proposals allow passing parameters, providing default parameters, destructuring, etc.; both proposals allow omitting parentheses if no parameters provided (tagged templates require some hacks to do this, though).

On the other hand, enabling this may cause some ambiguity; e.g. 42@foo(bar) may be treated as call expression rather than parametric extended numeric literal. Also, call expressions will require parenthesizing of an extended literal: (42@lazy)() === 42 (pretty weird way to create an IIFE, TBH).

Possible use cases include:

  1. Representing both dimensional and dimensionless quantities in scientific libraries using the same syntax and without a need to create a specific decorator for each SI unit and/or to handle primitive numbers in a special way (as dimensionless) in methods/functions. (Welp, defining specific decorators for each unit will make expressions much more readable and expressive, despite bloating code.)
  2. Adding metadata to values.
  3. Decorating numbers directly with @numericTemplate. (Again, that’s pretty useless, but provides consistency with other decorators, where built-in decorators may be applied directly.)

Though, if take into account possible ambiguity described above and a fact that decorators on numeric literals cannot be stacked like other decorators and tagged templates, dropping attempts to provide as much consistency as possible isn’t such a bad idea.

littledan commented 5 years ago

OK, I'm pretty convinced. Want to make a PR to update the explainer?

miyaokamarina commented 5 years ago

Done: https://github.com/tc39/proposal-extended-numeric-literals/pull/24.

hax commented 4 years ago

This brings ambiguity.

Theoretically, 42@foo could return anything, include function. In such case, (42@foo)() is same as 42@foo()() but not 42@foo().

It would be even interesting if you consider new X() which allow omit parens too. What new 42@foo(bar) means?

littledan commented 4 years ago

@hax Yes, @waldemarhorwat has previously raised this issue. We'll have to think this through a bit more before proceeding.

littledan commented 4 years ago

Unfortunately, I feel forced to conclude that we omit parameters for literal suffixes, based on the concern that @hax explained above.