Decorators for functions

Andrea Giammarchi andrea.giammarchi at gmail.com
Wed Oct 21 22:58:11 UTC 2015


last time I say this:

```js
(function () {'use strict'; class A {} console.log(A); } ());
```

That is `function  A` in Firefox nightly, and for some reason  `function
class A` in  Chrome but it  would  be `function A` in  every other browser.

There is no  way to distinguish between  function A and just a regular
function, meaning this will break portability and make life hard for using
the decorator with classes prototypes instead of of just functions.

The capitalized name is just a convention, not a standard defined constrain
... are you willing to lose this because you cannot use an already working
workaround or two parenthesis instead of a @ char ?

If yes, **why** if I might ask? It hasn't been  even a concern 'till this
thread now it's suddenly something that must be out?

Regards









On Wed, Oct 21, 2015 at 11:39 PM, Alexander Jones <alex at weej.com> wrote:

> Why stop at ES3?
>
> Point is this literally saves you two parens in exchange for one @ and a
> peculiar logical insertion after the = for the use cases discussed.
>
> Let's please collectively remember and acknowledge that this exists in
> Python because *they have no function literal syntax*. We do.
>
>
> On Wednesday, 21 October 2015, Yongxu Ren <renyongxu at gmail.com> wrote:
>
>> I agree with Andrea, basically nothing after es3 is a "must have", if we
>> apply the same argument.
>>
>> I see a lot possibilities of decorator, I think it would be great if it
>> can be used on any lvalue, or even statements.
>>
>> some of the application I can think of:
>> ```
>> //static type checking
>> @type(number,number,number)
>> function f(a,b){
>>         ....
>> }
>>
>> @debug(unitTestForFunction)
>> let f = (x) => .....
>>
>> @parallel
>> for(.......){.......}
>> ```
>> I think the best part of decorator is it can be processed by compiler or
>> polyfilled, so we can use them to instruct translator such as babel, to do
>> extra checking during development and drop them in production. It can also
>> be used by JET, if supported. Extra type checking, debugging can be ignored
>> by native engine, polyfilled to function that does nothing(as fallback if
>> no native support), or optimized as static typed function for performance.
>>
>> I'd love to see a limitless decorator that also allows browser/compiler
>> to receive hints from developers.
>>
>> On Wed, Oct 21, 2015 at 7:12 AM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>>> I agree it's not a "must have", considering what we lose if applied
>>> (portability) + you are back to broken portability with @meomize function
>>> ... VS meomize(function)
>>>
>>> So, I think portability is more important than some edge case without
>>> parenthesis around and if really wanted as a pattern,there is a workaround.
>>>
>>> Create an object to unpack it ... why not ... named functions? why not
>>> ... I'm used to write `{method:  function method() {}}` for debugging sake
>>> and I like named functions but going even more dirty with the workaround
>>> maybe an array to unpack would  make it less maintainable but less verbose
>>> too.
>>>
>>> It will still be portable,  which is all it matters to me.
>>>
>>> Regards
>>>
>>>
>>>
>>>
>>>
>>> On Wed, Oct 21, 2015 at 1:01 PM, Alexander Jones <alex at weej.com> wrote:
>>>
>>>> Although this works, it seems like a bit of a violation of
>>>> say-what-you-mean and dont-repeat-yourself to me. You have to write the
>>>> name of each function twice, and you are defining a shorthand object
>>>> literal just for the sake of unpacking it.
>>>>
>>>> If we must have syntax for this, I'd propose hijacking @ to mean
>>>> general paren-free invocation, using the same precedence rules as Coffee:
>>>>
>>>> ```js
>>>> const fibonacci = memoize(function(n) {...});
>>>> const fibonacci = @memoize function(n) {...};
>>>> const fib100 = @fibonacci 100;
>>>> @window.alert "If this syntax works for functions, why not let it work
>>>> for anything?";
>>>> ```
>>>>
>>>> But I must ask - why *exactly* do people have a problem with the extra
>>>> brackets again? Is it really just because we don't have good paredit or
>>>> other tree-based editing for JS yet? (Or do we?)
>>>>
>>>> On Wednesday, 21 October 2015, Andrea Giammarchi <
>>>> andrea.giammarchi at gmail.com> wrote:
>>>>
>>>>> Again, everything can be defined in a similar way, actually granting
>>>>> those function  cannot posibly be declared or redefined differently, being
>>>>> constants.
>>>>>
>>>>> ```js
>>>>>
>>>>> const {
>>>>>   assert,
>>>>>   log,
>>>>>   add
>>>>> } = {
>>>>>   @conditional(DEBUG)
>>>>>   assert(condition, message = "assertion failed.") {
>>>>>     if (!condition) throw new Error(message);
>>>>>   }
>>>>>
>>>>>   @conditional(TRACE)
>>>>>   log(message) {
>>>>>     return target => function () {
>>>>>        console.log(message);
>>>>>        return target.apply(this, arguments);
>>>>>     };
>>>>>   }
>>>>>
>>>>>   @metadata("design:paramtypes", () => [Number, Number])
>>>>>   @metadata("design:returntype", () => Number)
>>>>>   function add(a, b) {
>>>>>     return a + b;
>>>>>   }
>>>>>
>>>>> };
>>>>> ```
>>>>>
>>>>> Beside that, that gist is completely unreadable to my eyes, I guess it
>>>>> would take some time to be maintained as well if that was production code.
>>>>>
>>>>> The work around fixes all that, it keeps portability of the current
>>>>> proposal, and it ensure log will always be that log and nothing else in
>>>>> that very same scope +  strawberry on  top, less writing and always named
>>>>> functions.
>>>>>
>>>>> How cool is that?
>>>>>
>>>>> Best Regards
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Tue, Oct 20, 2015 at 8:26 PM, Ron Buckton <
>>>>> Ron.Buckton at microsoft.com> wrote:
>>>>>
>>>>>> I can think of numerous examples of how decorators could apply to
>>>>>> functions, and I’ve added them to a gist
>>>>>> <https://gist.github.com/rbuckton/37e944f7986e6833949e> [1] for
>>>>>> easier consumption. It’s true that simple decorators for functions can work
>>>>>> as simply as function calls, but this becomes a bit unwieldy if you need to
>>>>>> compose multiple decorators on a single function.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Consider a scenario combining decorators providing runtime type
>>>>>> information as an annotation with one that adds runtime type checking. With
>>>>>> decorators this might be:
>>>>>>
>>>>>>
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> @paramtypes(() => [Number, Number])
>>>>>>
>>>>>> @returntype(() => Number)
>>>>>>
>>>>>> @checked
>>>>>>
>>>>>> function add(x, y) { return x + y }
>>>>>>
>>>>>> ```
>>>>>>
>>>>>>
>>>>>>
>>>>>> If I just use function expressions, this is feasible if a bit awkward:
>>>>>>
>>>>>>
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> const add =
>>>>>>
>>>>>>     paramtypes(() => [Number, Number])(
>>>>>>
>>>>>>         returntype(() => Number)(
>>>>>>
>>>>>>             checked(
>>>>>>
>>>>>>                 function (x, y) { return x + y; })))
>>>>>>
>>>>>> ```
>>>>>>
>>>>>>
>>>>>>
>>>>>> It feels a bit developer-hostile to have to rebalance parentheses if
>>>>>> you want to add a decorator, and there are ASI hazards if you misplace an
>>>>>> opening paren. Also, you can no longer infer the function name “add” from
>>>>>> the const binding.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Using `::` isn’t a great replacement either, as there are many
>>>>>> hazards such as:
>>>>>>
>>>>>>
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> // The following means “call `decorator` with `this` bound to the
>>>>>> function object”.
>>>>>>
>>>>>> // Also, it becomes impossible to infer the function name “a” from
>>>>>> the let binding.
>>>>>>
>>>>>> let a = function() { }::decorator(x)
>>>>>>
>>>>>>
>>>>>>
>>>>>> let b = function() { }
>>>>>>
>>>>>> ::some.decorator(x) // ASI hazard as `::` can be either prefix or
>>>>>> infix.
>>>>>>
>>>>>> ```
>>>>>>
>>>>>>
>>>>>>
>>>>>> One of the initial drivers for decorators was class methods, as
>>>>>> there’s no expression context immediately inside the class body in which
>>>>>> you can use either of the above scenarios. This necessitated a declarative
>>>>>> form for decorators to allow these scenarios to exist. Having parity across
>>>>>> class methods, classes, and functions (of all kinds) presents a more
>>>>>> consistent story to developers. The upswing in decorator use in both
>>>>>> TypeScript and Babel has been very positive, with libraries like Angular
>>>>>> leveraging decorators heavily in their codebase. Since we introduced
>>>>>> decorators into TypeScript, we’ve had a fair bit of feedback requesting
>>>>>> support for function decorators.
>>>>>>
>>>>>>
>>>>>>
>>>>>> I do think function decorators should wait until the Class/Property
>>>>>> decorators proposal advances further along the standards track. Axel’s
>>>>>> initial concerns/questions around hoisting are valid and there isn’t a
>>>>>> clear consensus on the semantics for functions. That said, I’ve been mostly
>>>>>> in the camp of introducing TDZ for function declarations that have
>>>>>> decorators. Decorators are a new syntactic form and we have the opportunity
>>>>>> to communicate this caveat with the development community by the time the
>>>>>> feature lands. It seems easy enough to explain that:
>>>>>>
>>>>>>
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> @decorator
>>>>>>
>>>>>> function func() { }
>>>>>>
>>>>>> ```
>>>>>>
>>>>>>
>>>>>>
>>>>>> Is the equivalent of:
>>>>>>
>>>>>>
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> let func = @decorator function() { }
>>>>>>
>>>>>> ```
>>>>>>
>>>>>>
>>>>>>
>>>>>> Introducing TDZ allows to generally warn early as part of the static
>>>>>> semantics, so developers won’t fall into a well with respect to adding a
>>>>>> decorator to a function and not being able to quickly understand how that
>>>>>> change affects the behavior of their code.
>>>>>>
>>>>>>
>>>>>>
>>>>>> I’m not certain what the current plan of record is, but the best
>>>>>> approach may be:
>>>>>>
>>>>>>
>>>>>>
>>>>>> 1.       Advance and get consensus on the Class/Property decorators
>>>>>> proposal
>>>>>>
>>>>>> 2.       Draft a separate proposal for decorators on function
>>>>>> expressions, generator function expressions, and arrows
>>>>>>
>>>>>> 3.       Draft a separate proposal for decorators on function
>>>>>> declarations
>>>>>>
>>>>>>
>>>>>>
>>>>>> Steps 1 and 2 above shouldn’t be significantly difficult and don’t
>>>>>> necessarily introduce any major new semantics outside of the decorators
>>>>>> themselves. Step 3 covers a thornier issue as it not only introduces the
>>>>>> new semantics of decorators but also introduces side-effects due to
>>>>>> hoisting.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Ron
>>>>>>
>>>>>>
>>>>>>
>>>>>> [1] https://gist.github.com/rbuckton/37e944f7986e6833949e
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On
>>>>>> Behalf Of *Andrea Giammarchi
>>>>>> *Sent:* Tuesday, October 20, 2015 3:34 AM
>>>>>> *To:* Axel Rauschmayer <rauschma at icloud.com>
>>>>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org>
>>>>>> *Subject:* Re: Decorators for functions
>>>>>>
>>>>>>
>>>>>>
>>>>>> You haven't provided a single use-case example, like how are you
>>>>>> going to decorate a function or why.
>>>>>>
>>>>>>
>>>>>>
>>>>>> IMO if implemented it will be incompatible with non ES6 code unable
>>>>>> to distinguish between classes and functions unless fully transpiled,
>>>>>> making decorators less portable.
>>>>>>
>>>>>>
>>>>>>
>>>>>> One thing I like about current state is that you can use decorators
>>>>>> even in ES5 browsers [1]
>>>>>>
>>>>>>
>>>>>>
>>>>>> Just my 2 cents, Regards
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> [1] as shown in the second example of the universal mixin module
>>>>>> https://github.com/WebReflection/universal-mixin#universal-mixin-
>>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fWebReflection%2funiversal-mixin%23universal-mixin-&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=T1q%2bKVVIyc%2bNxSyG9Ri%2bmNAMPqq3p6Ydofoe1WQrg5U%3d>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Tue, Oct 20, 2015 at 10:30 AM, Axel Rauschmayer <
>>>>>> rauschma at icloud.com> wrote:
>>>>>>
>>>>>> https://github.com/wycats/javascript-decorators/blob/master/README.md
>>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fwycats%2fjavascript-decorators%2fblob%2fmaster%2fREADME.md&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=2fTFCt8Rrkx6pTvFLkcl8xfV5EKny35QpLPVTmm0aV8%3d>
>>>>>>
>>>>>> The decorator proposal does not include decorators for functions,
>>>>>> because it isn’t clear how to make them work in the face of hoisting.
>>>>>>
>>>>>> However, it would be great to have them. I see two possible solutions:
>>>>>>
>>>>>> – A decorator on a function declaration prevents hoisting.
>>>>>>
>>>>>> – Enable decorators for function expressions, arrow functions and
>>>>>> generator function expressions.
>>>>>>
>>>>>> Does either one of those make sense?
>>>>>>
>>>>>> Axel
>>>>>>
>>>>>> --
>>>>>> Dr. Axel Rauschmayer
>>>>>> axel at rauschma.de
>>>>>> rauschma.de
>>>>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2frauschma.de&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=Vclw%2fyI29j4WqkHWjTgaZtoL12pnJNCWYBJK4wTYVA0%3d>
>>>>>>
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> es-discuss mailing list
>>>>>> es-discuss at mozilla.org
>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fmail.mozilla.org%2flistinfo%2fes-discuss&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=7t2BTGHrR322y2keuKyyEhgwUSIOCCN3vzv9CbXzdn8%3d>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151021/2bfb3a47/attachment-0001.html>


More information about the es-discuss mailing list