proposal-extended-numeric-literals
proposal-extended-numeric-literals copied to clipboard
Passing arguments to numeric template?
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)
We could enable this; I was thinking about omitting the feature, though. Could you explain a little more about your use cases?
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:
- 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.)
- Adding metadata to values.
- 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.
OK, I'm pretty convinced. Want to make a PR to update the explainer?
Done: https://github.com/tc39/proposal-extended-numeric-literals/pull/24.
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?
new (42@foo(bar))new (42@foo)(bar)
@hax Yes, @waldemarhorwat has previously raised this issue. We'll have to think this through a bit more before proceeding.
Unfortunately, I feel forced to conclude that we omit parameters for literal suffixes, based on the concern that @hax explained above.