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,
[1] as shown in the second example of the universal mixin module WebReflection/universal-mixin#universal-mixin-
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- 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 > > 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 > > > > _______________________________________________ > 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/20151020/556d6479/attachment.html>
So wait, you agree there are valid use cases for decorating functions when they are methods on an object (although I don't see much along that line in the proposal). But if the function is "stand-alone" suddenly the use cases evaporate?
For example, I hack on and off on a framework involving transforming functions into self-updating versions of themselves. Of course I can write this as
self_updatify(function a() { })
but it would be more compact and readable to say
@self_updatify
function a() { }
Which is, please correct me if I'm wrong, all decorators are about. To take one example, Ember wants to use decorators not to get new functionality, but to make the writing of computed properties less ugly, among other reasons. (The fact that Ember makes little use of non-method functions may also be one reason for the low priority placed on figuring out how to decorate functions.)
We can work to develop more examples and motivations and use cases for decorated functions, although frankly it seems a little odd, as I mentioned above, that there could be compelling use cases for decorated methods but not for decorated functions. For the purposes of this discussion I will stipulate that having decorated functions is an idea worth pursuing. If you disagree, there's not point in reading further (but you might want to stop and ask yourself why if it's such a great idea to have decorated methods, no-one will ever want decorated functions).
The only problem as far as I am aware is how to handle hoisting.
AFAICS, hoisting is not an issue if the decorator has no side effects. Of course there is nothing wrong with writing decorators with side effects, and there are valid use cases for doing so, but they are rare. Furthermore, even if a decorator does have side-effects, in only some subset of such cases will the side effects together with hoisting result in unexpected behavior.
So to say that we will simply give up on decorated functions because of the few cases where decorators have side effects, and those side effects cause unexpected behavior due to hoisting, is really throwing out the baby with the bathwater. We are telling people that you cannot decorate functions at all, ever, or to decorate functions they must wrap them in a class or object, because of some potentially unexpected behavior in what is decidedly an edge case.
Various proposals have been made on this topic, including hoisting separately from decorating, hoisting and decorating at the same time, change hoisting behavior for decorated functions, etc. etc. Each of these ideas has its proponents and those who think it is the work of the devil. I will not go into the details of these approaches here, and to do so is actually a bit above my pay grade.
I would just say that it is odd in the extreme that a group of world-leading language designers would just throw in the towel when confronted with a pretty small roadbump, instead of figuring out ways to solve it. The alternative, which is to implement decorators only for methods and classes and leave out functions because we couldn't figure it out, seems like a major admission of failure.
Bob
So wait, you agree there are valid use cases for decorating functions when they are methods on an object (although I don't see much along that line in the proposal). But if the function is "stand-alone" suddenly the use cases evaporate? For example, I hack on and off on a framework involving transforming functions into self-updating versions of themselves. Of course I can write this as self_updatify(function a() { }) but it would be more compact and readable to say @self_updatify function a() { } Which is, please correct me if I'm wrong, all decorators are about. To take one example, Ember wants to use decorators not to get new functionality, but to make the writing of computed properties less ugly, among other reasons. (The fact that Ember makes little use of non-method functions may also be one reason for the low priority placed on figuring out how to decorate functions.) We can work to develop more examples and motivations and use cases for decorated functions, although frankly it seems a little odd, as I mentioned above, that there could be compelling use cases for decorated methods but not for decorated functions. For the purposes of this discussion I will stipulate that having decorated functions is an idea worth pursuing. If you disagree, there's not point in reading further (but you might want to stop and ask yourself why if it's such a great idea to have decorated methods, no-one will ever want decorated functions). The only problem as far as I am aware is how to handle hoisting. AFAICS, hoisting is not an issue if the decorator has no side effects. Of course there is nothing wrong with writing decorators with side effects, and there are valid use cases for doing so, but they are rare. Furthermore, even if a decorator does have side-effects, in only some subset of such cases will the side effects together with hoisting result in unexpected behavior. So to say that we will simply give up on decorated functions because of the few cases where decorators have side effects, and those side effects cause unexpected behavior due to hoisting, is really throwing out the baby with the bathwater. We are telling people that you cannot decorate functions at all, ever, or to decorate functions they must wrap them in a class or object, because of some potentially unexpected behavior in what is decidedly an edge case. Various proposals have been made on this topic, including hoisting separately from decorating, hoisting and decorating at the same time, change hoisting behavior for decorated functions, etc. etc. Each of these ideas has its proponents and those who think it is the work of the devil. I will not go into the details of these approaches here, and to do so is actually a bit above my pay grade. I would just say that it is odd in the extreme that a group of world-leading language designers would just throw in the towel when confronted with a pretty small roadbump, instead of figuring out ways to solve it. The alternative, which is to implement decorators only for methods and classes and leave out functions because we couldn't figure it out, seems like a major admission of failure. Bob On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: > 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- > > 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 >> >> 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 >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/e3de969e/attachment.html>
You completely misunderstood me Bob, I don't think there's any valid use case for functions at all, including methods and ... .specially methods!!!
I was thinking about decorators for classes, when you enrich their prototype in case the decorator receives a function instead of an object, or you enrich the object in every other case.
You transform at runtime prototype methods??? Good for you, but that's something I'd never do, unless we are talking about lazy evaluation on the instance, where I don't see how lazy evaluation for an inherited method has anything to do with functions decorators.
The difference is huge, methods will most likely have a this
reference to
be promoted on eventually, in the other case you have a function that
unless its body has "switches" can cannot really promote much by itself and
passing it around as higher order function that mutates? ... yak!
As summary: does anyone has a valid use case for a generic function decorator? 'cause I still don't see one, and having decorators for any sort of function would be problematic in terms of code portability, which is all I am saying.
You completely misunderstood me Bob, I don't think there's any valid use case for functions at all, including methods and ... .**specially** methods!!! I was thinking about decorators for classes, when you enrich their prototype in case the decorator receives a function instead of an object, or you enrich the object in every other case. You transform at runtime prototype methods??? Good for you, but that's something I'd never do, unless we are talking about lazy evaluation on the instance, where I don't see how lazy evaluation for an inherited method has anything to do with *functions* decorators. The difference is huge, methods will most likely have a `this` reference to be promoted on eventually, in the other case you have a function that unless its body has "switches" can cannot really promote much by itself and passing it around as higher order function that mutates? ... yak! As summary: does anyone has a valid use case for a generic function decorator? 'cause I still don't see one, and having decorators for any sort of function would be problematic in terms of code portability, which is all I am saying. Regards On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: > So wait, you agree there are valid use cases for decorating functions when > they are methods on an object (although I don't see much along that line in > the proposal). But if the function is "stand-alone" suddenly the use cases > evaporate? > > For example, I hack on and off on a framework involving transforming > functions into self-updating versions of themselves. Of course I can write > this as > > self_updatify(function a() { }) > > but it would be more compact and readable to say > > @self_updatify > function a() { } > > Which is, please correct me if I'm wrong, all decorators are about. To > take one example, Ember wants to use decorators not to get new > functionality, but to make the writing of computed properties less ugly, > among other reasons. (The fact that Ember makes little use of non-method > functions may also be one reason for the low priority placed on figuring > out how to decorate functions.) > > We can work to develop more examples and motivations and use cases for > decorated functions, although frankly it seems a little odd, as I mentioned > above, that there could be compelling use cases for decorated methods but > not for decorated functions. For the purposes of this discussion I will > stipulate that having decorated functions is an idea worth pursuing. If you > disagree, there's not point in reading further (but you might want to stop > and ask yourself why if it's such a great idea to have decorated methods, > no-one will ever want decorated functions). > > The only problem as far as I am aware is how to handle hoisting. > > AFAICS, hoisting is not an issue if the decorator has no side effects. Of > course there is nothing wrong with writing decorators with side effects, > and there are valid use cases for doing so, but they are rare. Furthermore, > even if a decorator does have side-effects, in only some subset of such > cases will the side effects together with hoisting result in unexpected > behavior. > > So to say that we will simply give up on decorated functions because of > the few cases where decorators have side effects, and those side effects > cause unexpected behavior due to hoisting, is really throwing out the baby > with the bathwater. We are telling people that you cannot decorate > functions at all, ever, or to decorate functions they must wrap them in a > class or object, because of some potentially unexpected behavior in what is > decidedly an edge case. > > Various proposals have been made on this topic, including hoisting > separately from decorating, hoisting and decorating at the same time, > change hoisting behavior for decorated functions, etc. etc. Each of these > ideas has its proponents and those who think it is the work of the devil. I > will not go into the details of these approaches here, and to do so is > actually a bit above my pay grade. > > I would just say that it is odd in the extreme that a group of > world-leading language designers would just throw in the towel when > confronted with a pretty small roadbump, instead of figuring out ways to > solve it. The alternative, which is to implement decorators only for > methods and classes and leave out functions because we couldn't figure it > out, seems like a major admission of failure. > > Bob > > > On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> 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- >> >> 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 >>> >>> 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 >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/be6293eb/attachment-0001.html>
Why not just do:
const {myFunc} = {
@someDecorator;
myFunc() {
}
};
- Matthew Robb
Why not just do: ``` const {myFunc} = { @someDecorator; myFunc() { } }; ``` - Matthew Robb On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: > You completely misunderstood me Bob, I don't think there's any valid use > case for functions at all, including methods and ... .**specially** > methods!!! > > I was thinking about decorators for classes, when you enrich their > prototype in case the decorator receives a function instead of an object, > or you enrich the object in every other case. > > You transform at runtime prototype methods??? Good for you, but that's > something I'd never do, unless we are talking about lazy evaluation on the > instance, where I don't see how lazy evaluation for an inherited method has > anything to do with *functions* decorators. > > The difference is huge, methods will most likely have a `this` reference > to be promoted on eventually, in the other case you have a function that > unless its body has "switches" can cannot really promote much by itself and > passing it around as higher order function that mutates? ... yak! > > As summary: does anyone has a valid use case for a generic function > decorator? 'cause I still don't see one, and having decorators for any sort > of function would be problematic in terms of code portability, which is all > I am saying. > > Regards > > > > > > > > > > > On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: > >> So wait, you agree there are valid use cases for decorating functions >> when they are methods on an object (although I don't see much along that >> line in the proposal). But if the function is "stand-alone" suddenly the >> use cases evaporate? >> >> For example, I hack on and off on a framework involving transforming >> functions into self-updating versions of themselves. Of course I can write >> this as >> >> self_updatify(function a() { }) >> >> but it would be more compact and readable to say >> >> @self_updatify >> function a() { } >> >> Which is, please correct me if I'm wrong, all decorators are about. To >> take one example, Ember wants to use decorators not to get new >> functionality, but to make the writing of computed properties less ugly, >> among other reasons. (The fact that Ember makes little use of non-method >> functions may also be one reason for the low priority placed on figuring >> out how to decorate functions.) >> >> We can work to develop more examples and motivations and use cases for >> decorated functions, although frankly it seems a little odd, as I mentioned >> above, that there could be compelling use cases for decorated methods but >> not for decorated functions. For the purposes of this discussion I will >> stipulate that having decorated functions is an idea worth pursuing. If you >> disagree, there's not point in reading further (but you might want to stop >> and ask yourself why if it's such a great idea to have decorated methods, >> no-one will ever want decorated functions). >> >> The only problem as far as I am aware is how to handle hoisting. >> >> AFAICS, hoisting is not an issue if the decorator has no side effects. Of >> course there is nothing wrong with writing decorators with side effects, >> and there are valid use cases for doing so, but they are rare. Furthermore, >> even if a decorator does have side-effects, in only some subset of such >> cases will the side effects together with hoisting result in unexpected >> behavior. >> >> So to say that we will simply give up on decorated functions because of >> the few cases where decorators have side effects, and those side effects >> cause unexpected behavior due to hoisting, is really throwing out the baby >> with the bathwater. We are telling people that you cannot decorate >> functions at all, ever, or to decorate functions they must wrap them in a >> class or object, because of some potentially unexpected behavior in what is >> decidedly an edge case. >> >> Various proposals have been made on this topic, including hoisting >> separately from decorating, hoisting and decorating at the same time, >> change hoisting behavior for decorated functions, etc. etc. Each of these >> ideas has its proponents and those who think it is the work of the devil. I >> will not go into the details of these approaches here, and to do so is >> actually a bit above my pay grade. >> >> I would just say that it is odd in the extreme that a group of >> world-leading language designers would just throw in the towel when >> confronted with a pretty small roadbump, instead of figuring out ways to >> solve it. The alternative, which is to implement decorators only for >> methods and classes and leave out functions because we couldn't figure it >> out, seems like a major admission of failure. >> >> Bob >> >> >> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> 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- >>> >>> 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 >>>> >>>> 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 >>>> >>> >> > > _______________________________________________ > 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/20151020/dc1d0fe6/attachment.html>
FWIW that would make code portable, accordingly with current proposal, the object is received, the descriptor and its name are clear. I personally wouldn't mind that pattern, yet I'm curious about use cases for functions decorators.
FWIW that would make code portable, accordingly with current proposal, the object is received, the descriptor and its name are clear. I personally wouldn't mind that pattern, yet I'm curious about use cases for functions decorators. Regards On Tue, Oct 20, 2015 at 2:18 PM, Matthew Robb <matthewwrobb at gmail.com> wrote: > Why not just do: > > ``` > const {myFunc} = { > @someDecorator; > myFunc() { > > } > }; > ``` > > > - Matthew Robb > > On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> You completely misunderstood me Bob, I don't think there's any valid use >> case for functions at all, including methods and ... .**specially** >> methods!!! >> >> I was thinking about decorators for classes, when you enrich their >> prototype in case the decorator receives a function instead of an object, >> or you enrich the object in every other case. >> >> You transform at runtime prototype methods??? Good for you, but that's >> something I'd never do, unless we are talking about lazy evaluation on the >> instance, where I don't see how lazy evaluation for an inherited method has >> anything to do with *functions* decorators. >> >> The difference is huge, methods will most likely have a `this` reference >> to be promoted on eventually, in the other case you have a function that >> unless its body has "switches" can cannot really promote much by itself and >> passing it around as higher order function that mutates? ... yak! >> >> As summary: does anyone has a valid use case for a generic function >> decorator? 'cause I still don't see one, and having decorators for any sort >> of function would be problematic in terms of code portability, which is all >> I am saying. >> >> Regards >> >> >> >> >> >> >> >> >> >> >> On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: >> >>> So wait, you agree there are valid use cases for decorating functions >>> when they are methods on an object (although I don't see much along that >>> line in the proposal). But if the function is "stand-alone" suddenly the >>> use cases evaporate? >>> >>> For example, I hack on and off on a framework involving transforming >>> functions into self-updating versions of themselves. Of course I can write >>> this as >>> >>> self_updatify(function a() { }) >>> >>> but it would be more compact and readable to say >>> >>> @self_updatify >>> function a() { } >>> >>> Which is, please correct me if I'm wrong, all decorators are about. To >>> take one example, Ember wants to use decorators not to get new >>> functionality, but to make the writing of computed properties less ugly, >>> among other reasons. (The fact that Ember makes little use of non-method >>> functions may also be one reason for the low priority placed on figuring >>> out how to decorate functions.) >>> >>> We can work to develop more examples and motivations and use cases for >>> decorated functions, although frankly it seems a little odd, as I mentioned >>> above, that there could be compelling use cases for decorated methods but >>> not for decorated functions. For the purposes of this discussion I will >>> stipulate that having decorated functions is an idea worth pursuing. If you >>> disagree, there's not point in reading further (but you might want to stop >>> and ask yourself why if it's such a great idea to have decorated methods, >>> no-one will ever want decorated functions). >>> >>> The only problem as far as I am aware is how to handle hoisting. >>> >>> AFAICS, hoisting is not an issue if the decorator has no side effects. >>> Of course there is nothing wrong with writing decorators with side effects, >>> and there are valid use cases for doing so, but they are rare. Furthermore, >>> even if a decorator does have side-effects, in only some subset of such >>> cases will the side effects together with hoisting result in unexpected >>> behavior. >>> >>> So to say that we will simply give up on decorated functions because of >>> the few cases where decorators have side effects, and those side effects >>> cause unexpected behavior due to hoisting, is really throwing out the baby >>> with the bathwater. We are telling people that you cannot decorate >>> functions at all, ever, or to decorate functions they must wrap them in a >>> class or object, because of some potentially unexpected behavior in what is >>> decidedly an edge case. >>> >>> Various proposals have been made on this topic, including hoisting >>> separately from decorating, hoisting and decorating at the same time, >>> change hoisting behavior for decorated functions, etc. etc. Each of these >>> ideas has its proponents and those who think it is the work of the devil. I >>> will not go into the details of these approaches here, and to do so is >>> actually a bit above my pay grade. >>> >>> I would just say that it is odd in the extreme that a group of >>> world-leading language designers would just throw in the towel when >>> confronted with a pretty small roadbump, instead of figuring out ways to >>> solve it. The alternative, which is to implement decorators only for >>> methods and classes and leave out functions because we couldn't figure it >>> out, seems like a major admission of failure. >>> >>> Bob >>> >>> >>> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> 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- >>>> >>>> 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 >>>>> >>>>> 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 >>>>> >>>> >>> >> >> _______________________________________________ >> 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/20151020/288fef5a/attachment-0001.html>
Drive-by-comment:
On 20 October 2015 at 14:40, Bob Myers <rtm at gol.com> wrote:
AFAICS, hoisting is not an issue if the decorator has no side effects.
Not so. Initialisation order is another issue. Consider:
var x = 0 @bla(x) function f() {}
Also, as a side note, pretty much everything in JavaScript potentially has side effects.
Drive-by-comment: On 20 October 2015 at 14:40, Bob Myers <rtm at gol.com> wrote: > AFAICS, hoisting is not an issue if the decorator has no side effects. Not so. Initialisation order is another issue. Consider: var x = 0 @bla(x) function f() {} Also, as a side note, pretty much *everything* in JavaScript potentially has side effects. /Andreas
I would just say that it is odd in the extreme that a group of world-leading language designers would just throw in the towel when confronted with a pretty small roadbump, instead of figuring out ways to solve it.
Another drive-by...
The trick is introducing new features without exploding the number of rules which must be remembered in order to use that feature.
> > I would just say that it is odd in the extreme that a group of > world-leading language designers would just throw in the towel when > confronted with a pretty small roadbump, instead of figuring out ways to > solve it. > Another drive-by... The trick is introducing new features without exploding the number of rules which must be remembered in order to use that feature. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/7848355f/attachment.html>
More drive-bys.
I could see decorators as a nice way to define "functional" behavior for generic functions:
@curried var add = (a, b) => a + b;
@memoize var fetch = (url) => /* logic */;
Eli Perelman
More drive-bys. I could see decorators as a nice way to define "functional" behavior for generic functions: @curried var add = (a, b) => a + b; @memoize var fetch = (url) => /* logic */; Eli Perelman On Tue, Oct 20, 2015 at 8:42 AM, Kevin Smith <zenparsing at gmail.com> wrote: > I would just say that it is odd in the extreme that a group of >> world-leading language designers would just throw in the towel when >> confronted with a pretty small roadbump, instead of figuring out ways to >> solve it. >> > > Another drive-by... > > The trick is introducing new features without exploding the number of > rules which must be remembered in order to use that feature. > > > _______________________________________________ > 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/20151020/be609dc9/attachment.html>
Decorators can be both used to wrap things and to annotate them. For
example, here we're setting a flag with the web.method
function which is
used by by this fictional 'web' framework. The others are used as
middleware that modify the function arguments at each step.
export default
@web.method('post')
@web.parsesJSON()
@web.expectsBody({
emailAddress: String, password: String,
})
function handleLogIn(req, res, body){
// ...
}
In this example we have a React component that's just a simple function. We want to wrap it with a high order component.
@providesSomething()
function MyComponent({something}){
// ...
}
Here we're using dependency injection:
@di.provide(Calculator)
function add(calc, a, b){
return calc.add(a, b);
}
add(1, 2) === 3
I'm not completely sold on if these are good ideas. It might be more confusing than it's worth.
Decorators can be both used to wrap things and to annotate them. For example, here we're setting a flag with the `web.method` function which is used by by this fictional 'web' framework. The others are used as middleware that modify the function arguments at each step. ```js export default @web.method('post') @web.parsesJSON() @web.expectsBody({ emailAddress: String, password: String, }) function handleLogIn(req, res, body){ // ... } ``` In this example we have a React component that's just a simple function. We want to wrap it with a high order component. ```js @providesSomething() function MyComponent({something}){ // ... } ``` Here we're using dependency injection: ```js @di.provide(Calculator) function add(calc, a, b){ return calc.add(a, b); } add(1, 2) === 3 ``` I'm not completely sold on if these are good ideas. It might be more confusing than it's worth. On Tue, Oct 20, 2015 at 7:23 AM, Eli Perelman <eli at eliperelman.com> wrote: > More drive-bys. > > I could see decorators as a nice way to define "functional" behavior for > generic functions: > > @curried > var add = (a, b) => a + b; > > @memoize > var fetch = (url) => /* logic */; > > Eli Perelman > > On Tue, Oct 20, 2015 at 8:42 AM, Kevin Smith <zenparsing at gmail.com> wrote: > >> I would just say that it is odd in the extreme that a group of >>> world-leading language designers would just throw in the towel when >>> confronted with a pretty small roadbump, instead of figuring out ways to >>> solve it. >>> >> >> Another drive-by... >> >> The trick is introducing new features without exploding the number of >> rules which must be remembered in order to use that feature. >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > _______________________________________________ > 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/20151020/7b53249b/attachment.html>
If you don't pass the surrounding object / prototype I don't personally see
any added value from using fn.bind(null, Calculator)
or simply
dl.provide(Calculator, function add(calc, a, b) {})
Specially the export example would make my eyes bleed once the export is inside curly brackets: I've instantly no idea if I'm exporting an object through decorators and methods or just functions.
True that methods won't have the function
bit but we're back to the
portability issue I've mentioned, which is not just a bump in the road,
it's a lock in ES6 only, transpiled or not, which reminds me issues with
modules between Python 3 and 2 ... I wish we'd never go even close to that
situation with decorators, which are powerful and right now portable.
Are we really willing to lose current portability considering there is a simple work around and even the only dev with concrete examples is not sold it's a good approach rather than just a more confusing one?
Wouldn't be wise to eventually bring in current proposal and reserve eventually the function bit for 2017 so that the migration to the new decorator feature would be less problematic?
After all I don't see any problem in implementing the idea later on so that going out with just current proposal is past and future friendly.
Again just my thoughts
If you don't pass the surrounding object / prototype I don't personally see any added value from using `fn.bind(null, Calculator)` or simply `dl.provide(Calculator, function add(calc, a, b) {})` Specially the export example would make my eyes bleed once the export is inside curly brackets: I've instantly no idea if I'm exporting an object through decorators and methods or just functions. True that methods won't have the `function` bit but we're back to the portability issue I've mentioned, which is not just a bump in the road, it's a lock in ES6 only, transpiled or not, which reminds me issues with modules between Python 3 and 2 ... I wish we'd never go even close to that situation with decorators, which are powerful and right now portable. Are we really willing to lose current portability considering there is a simple work around and even the only dev with concrete examples is not sold it's a good approach rather than just a more confusing one? Wouldn't be wise to eventually bring in current proposal and reserve eventually the function bit for 2017 so that the migration to the new decorator feature would be less problematic? After all I don't see any problem in implementing the idea later on so that going out with just current proposal is past and future friendly. Again just my thoughts Regards On Tue, Oct 20, 2015 at 3:40 PM, Frankie Bagnardi <f.bagnardi at gmail.com> wrote: > Decorators can be both used to wrap things and to annotate them. For > example, here we're setting a flag with the `web.method` function which is > used by by this fictional 'web' framework. The others are used as > middleware that modify the function arguments at each step. > > ```js > export default > @web.method('post') > @web.parsesJSON() > @web.expectsBody({ > emailAddress: String, password: String, > }) > function handleLogIn(req, res, body){ > // ... > } > ``` > > In this example we have a React component that's just a simple function. > We want to wrap it with a high order component. > > ```js > @providesSomething() > function MyComponent({something}){ > // ... > } > ``` > > Here we're using dependency injection: > > ```js > @di.provide(Calculator) > function add(calc, a, b){ > return calc.add(a, b); > } > > add(1, 2) === 3 > ``` > > I'm not completely sold on if these are good ideas. It might be more > confusing than it's worth. > > > On Tue, Oct 20, 2015 at 7:23 AM, Eli Perelman <eli at eliperelman.com> wrote: > >> More drive-bys. >> >> I could see decorators as a nice way to define "functional" behavior for >> generic functions: >> >> @curried >> var add = (a, b) => a + b; >> >> @memoize >> var fetch = (url) => /* logic */; >> >> Eli Perelman >> >> On Tue, Oct 20, 2015 at 8:42 AM, Kevin Smith <zenparsing at gmail.com> >> wrote: >> >>> I would just say that it is odd in the extreme that a group of >>>> world-leading language designers would just throw in the towel when >>>> confronted with a pretty small roadbump, instead of figuring out ways to >>>> solve it. >>>> >>> >>> Another drive-by... >>> >>> The trick is introducing new features without exploding the number of >>> rules which must be remembered in order to use that feature. >>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > _______________________________________________ > 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/20151020/2ec1b7d6/attachment-0001.html>
I would have to agree with Andrea here. I don't see any benefits
decorated functions, e.g. @memoize function inc(x) { return x + 1 }
would provide other than syntax over const inc = memoize(x => x + 1)
.
I would have to agree with Andrea here. I don't see any benefits decorated functions, e.g. `@memoize function inc(x) { return x + 1 }` would provide other than syntax over `const inc = memoize(x => x + 1)`. On Tue, Oct 20, 2015 at 11:00 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote: > If you don't pass the surrounding object / prototype I don't personally see > any added value from using `fn.bind(null, Calculator)` or simply > `dl.provide(Calculator, function add(calc, a, b) {})` > > Specially the export example would make my eyes bleed once the export is > inside curly brackets: I've instantly no idea if I'm exporting an object > through decorators and methods or just functions. > > True that methods won't have the `function` bit but we're back to the > portability issue I've mentioned, which is not just a bump in the road, it's > a lock in ES6 only, transpiled or not, which reminds me issues with modules > between Python 3 and 2 ... I wish we'd never go even close to that situation > with decorators, which are powerful and right now portable. > > Are we really willing to lose current portability considering there is a > simple work around and even the only dev with concrete examples is not sold > it's a good approach rather than just a more confusing one? > > Wouldn't be wise to eventually bring in current proposal and reserve > eventually the function bit for 2017 so that the migration to the new > decorator feature would be less problematic? > > After all I don't see any problem in implementing the idea later on so that > going out with just current proposal is past and future friendly. > > Again just my thoughts > > Regards > > > On Tue, Oct 20, 2015 at 3:40 PM, Frankie Bagnardi <f.bagnardi at gmail.com> > wrote: >> >> Decorators can be both used to wrap things and to annotate them. For >> example, here we're setting a flag with the `web.method` function which is >> used by by this fictional 'web' framework. The others are used as middleware >> that modify the function arguments at each step. >> >> ```js >> export default >> @web.method('post') >> @web.parsesJSON() >> @web.expectsBody({ >> emailAddress: String, password: String, >> }) >> function handleLogIn(req, res, body){ >> // ... >> } >> ``` >> >> In this example we have a React component that's just a simple function. >> We want to wrap it with a high order component. >> >> ```js >> @providesSomething() >> function MyComponent({something}){ >> // ... >> } >> ``` >> >> Here we're using dependency injection: >> >> ```js >> @di.provide(Calculator) >> function add(calc, a, b){ >> return calc.add(a, b); >> } >> >> add(1, 2) === 3 >> ``` >> >> I'm not completely sold on if these are good ideas. It might be more >> confusing than it's worth. >> >> >> On Tue, Oct 20, 2015 at 7:23 AM, Eli Perelman <eli at eliperelman.com> wrote: >>> >>> More drive-bys. >>> >>> I could see decorators as a nice way to define "functional" behavior for >>> generic functions: >>> >>> @curried >>> var add = (a, b) => a + b; >>> >>> @memoize >>> var fetch = (url) => /* logic */; >>> >>> Eli Perelman >>> >>> On Tue, Oct 20, 2015 at 8:42 AM, Kevin Smith <zenparsing at gmail.com> >>> wrote: >>>>> >>>>> I would just say that it is odd in the extreme that a group of >>>>> world-leading language designers would just throw in the towel when >>>>> confronted with a pretty small roadbump, instead of figuring out ways to >>>>> solve it. >>>> >>>> >>>> Another drive-by... >>>> >>>> The trick is introducing new features without exploding the number of >>>> rules which must be remembered in order to use that feature. >>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > -- Isiah Meadows
You completely misunderstood me Bob.
Sorry about that.
I was thinking about decorators for classes, when you enrich their
prototype in case the decorator receives a function instead of an object, or you enrich the object in every other case.
Am I understanding this right that you are thinking of decorators as a type of trait mechanism?
As I understand it, decorators are pure sugar. I like sugar as much as the next guy, as long as it addresses common use cases, helps us write more readable, maintainable code, and doesn't eat too much into future syntax space. But I am on the fence about decorators.
It's worth noting that some kinds of decorators could possibly be handled
via ::
syntax:
(function() { })::decorate_me()
However, it is worthwhile considering the Ember "computed property" use case. For those who don't know Ember, computed properties recompute themselves on demand when their dependencies change. This requires the dependencies to be declared somehow. Then, the dependencies need to be retrieved again within the function.
The classic syntax for writing computed properties is:
foo: Ember.computed('dep1', 'dep2', function() { return this.get('dep1') +
this.get('dep2'); })
An alternative in widespread use is hardly prettier, and requires polluting the function prototype:
foo: function() { return this.get('dep1') + this.get('dep2');
}.computed('dep1', 'dep2')
The reason the Ember folks latched on to decorators is because they want to write this:
@computed('dep1', 'dep2')
foo(dep1, dep2) { return dep1 + dep2; }
and that is indeed much better. To accomplish this, the computed
decorator would be roughly written as
function computed(...deps) {
return function(target, name, descriptor) {
var undecorated = descriptor.value;
descriptor.value = undecorated.apply(this, deps.map(dep =>
this.get(dep));
return descriptor;
};
}
The above is meant merely for illustrative purposes.
The sweetness of the resulting sugar should attract a fair number of flies.
-- Bob
> You completely misunderstood me Bob. Sorry about that. > I was thinking about decorators for classes, when you enrich their prototype in case the decorator receives a function instead of an object, or you enrich the object in every other case. Am I understanding this right that you are thinking of decorators as a type of trait mechanism? As I understand it, decorators are pure sugar. I like sugar as much as the next guy, as long as it addresses common use cases, helps us write more readable, maintainable code, and doesn't eat too much into future syntax space. But I am on the fence about decorators. It's worth noting that some kinds of decorators could possibly be handled via `::` syntax: (function() { })::decorate_me() However, it is worthwhile considering the Ember "computed property" use case. For those who don't know Ember, computed properties recompute themselves on demand when their dependencies change. This requires the dependencies to be declared somehow. Then, the dependencies need to be retrieved again within the function. The classic syntax for writing computed properties is: ```js foo: Ember.computed('dep1', 'dep2', function() { return this.get('dep1') + this.get('dep2'); }) ``` An alternative in widespread use is hardly prettier, and requires polluting the function prototype: ```js foo: function() { return this.get('dep1') + this.get('dep2'); }.computed('dep1', 'dep2') ``` The reason the Ember folks latched on to decorators is because they want to write this: ```js @computed('dep1', 'dep2') foo(dep1, dep2) { return dep1 + dep2; } ``` and that is indeed much better. To accomplish this, the `computed` decorator would be roughly written as ```js function computed(...deps) { return function(target, name, descriptor) { var undecorated = descriptor.value; descriptor.value = undecorated.apply(this, deps.map(dep => this.get(dep)); return descriptor; }; } ``` The above is meant merely for illustrative purposes. The sweetness of the resulting sugar should attract a fair number of flies. -- Bob On Tue, Oct 20, 2015 at 6:30 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/161f0af5/attachment.html>
Bob
Am I understanding this right that you are thinking of decorators as a
type of trait mechanism?
absolutely, which is what I've linked at the beginning ( universal-mixin module that already works with "ES7" proposed decorator syntax down to ES3 )
Your last example
@computed('dep1', 'dep2')
foo(dep1, dep2) { return dep1 + dep2; }
it's about prototype/object method decoration, which is OK as use case 'cause it sends the object/prototype as a target, the name 'foot' and the descriptor with the function as its value.
I'm absolutely fine with that because it's contextual. If you have only the function without a target though ... no that is the problem I am talking about, and it's purely related to portability of the proposal itself: right now is just sugar with a context (class/object), if we have to consider functions as functions, not as method and not as constructors (ES5/3) then we have a portability problem and it would be a pity because decorators are a wonderful migration pattern, as they are proposed now.
Add functions and goodbye portability in non transpiled code.
Hope it's clear what is my (actually) only concern in introducing extra specifications for functions only: few benefits, possibly more code to write, broken backward portability for pure /clean environments that don't want/have/use transpilers (nodejs, micro controlelrs, espruino, Yun etc)
Best
Bob > Am I understanding this right that you are thinking of decorators as a type of trait mechanism? absolutely, which is what I've linked at the beginning ( universal-mixin module that already works with "ES7" proposed decorator syntax down to ES3 ) Your last example ```js @computed('dep1', 'dep2') foo(dep1, dep2) { return dep1 + dep2; } ``` it's about prototype/object method decoration, which is OK as use case 'cause it sends the object/prototype as a target, the name 'foot' and the descriptor with the function as its value. I'm absolutely fine with that because it's contextual. If you have **only** the function without a target though ... no that is the problem I am talking about, and it's purely related to portability of the proposal itself: right now is just sugar with a context (class/object), if we have to consider functions as functions, not as method and not as constructors (ES5/3) then we have a portability problem and it would be a pity because decorators are a wonderful migration pattern, as they are proposed now. Add functions and goodbye portability in non transpiled code. Hope it's clear what is my (actually) only concern in introducing extra specifications for functions only: few benefits, possibly more code to write, broken backward portability for pure /clean environments that don't want/have/use transpilers (nodejs, micro controlelrs, espruino, Yun etc) Best Regards On Tue, Oct 20, 2015 at 5:24 PM, Bob Myers <rtm at gol.com> wrote: > > You completely misunderstood me Bob. > > Sorry about that. > > > I was thinking about decorators for classes, when you enrich their > prototype in case the decorator receives a function instead of an object, > or you enrich the object in every other case. > > Am I understanding this right that you are thinking of decorators as a > type of trait mechanism? > > As I understand it, decorators are pure sugar. I like sugar as much as the > next guy, as long as it addresses common use cases, helps us write more > readable, maintainable code, and doesn't eat too much into future syntax > space. But I am on the fence about decorators. > > It's worth noting that some kinds of decorators could possibly be handled > via `::` syntax: > > (function() { })::decorate_me() > > However, it is worthwhile considering the Ember "computed property" use > case. For those who don't know Ember, computed properties recompute > themselves on demand when their dependencies change. This requires the > dependencies to be declared somehow. Then, the dependencies need to be > retrieved again within the function. > > The classic syntax for writing computed properties is: > > ```js > foo: Ember.computed('dep1', 'dep2', function() { return this.get('dep1') + > this.get('dep2'); }) > ``` > > An alternative in widespread use is hardly prettier, and requires > polluting the function prototype: > > ```js > foo: function() { return this.get('dep1') + this.get('dep2'); > }.computed('dep1', 'dep2') > ``` > > The reason the Ember folks latched on to decorators is because they want > to write this: > > ```js > @computed('dep1', 'dep2') > foo(dep1, dep2) { return dep1 + dep2; } > ``` > > and that is indeed much better. To accomplish this, the `computed` > decorator would be roughly written as > > ```js > function computed(...deps) { > return function(target, name, descriptor) { > var undecorated = descriptor.value; > descriptor.value = undecorated.apply(this, deps.map(dep => > this.get(dep)); > return descriptor; > }; > } > ``` > > The above is meant merely for illustrative purposes. > > The sweetness of the resulting sugar should attract a fair number of flies. > > -- > Bob > > On Tue, Oct 20, 2015 at 6:30 PM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/f399d667/attachment-0001.html>
I can think of numerous examples of how decorators could apply to functions, and I’ve added them to a gistgist.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:
@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:
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:
// 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:
@decorator
function func() { }
Is the equivalent of:
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:
-
Advance and get consensus on the Class/Property decorators proposal
-
Draft a separate proposal for decorators on function expressions, generator function expressions, and arrows
-
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] 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,
[1] as shown in the second example of the universal mixin module WebReflection/universal-mixin#universal-mixin-na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FWebReflection%2Funiversal-mixin%23universal-mixin-&data=01|01|ron.buckton%40microsoft.com|50c27148ba3543c448f608d2d939f7c4|72f988bf86f141af91ab2d7cd011db47|1&sdata=T1q%2BKVVIyc%2BNxSyG9Ri%2BmNAMPqq3p6Ydofoe1WQrg5U%3D
On Tue, Oct 20, 2015 at 10:30 AM, Axel Rauschmayer <rauschma at icloud.com<mailto:rauschma at icloud.com>> wrote:
wycats/javascript-decorators/blob/master/README.mdna01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fwycats%2Fjavascript-decorators%2Fblob%2Fmaster%2FREADME.md&data=01|01|ron.buckton%40microsoft.com|50c27148ba3543c448f608d2d939f7c4|72f988bf86f141af91ab2d7cd011db47|1&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<mailto:axel at rauschma.de>
rauschma.dena01.safelinks.protection.outlook.com/?url=http%3A%2F%2Frauschma.de&data=01|01|ron.buckton%40microsoft.com|50c27148ba3543c448f608d2d939f7c4|72f988bf86f141af91ab2d7cd011db47|1&sdata=Vclw%2FyI29j4WqkHWjTgaZtoL12pnJNCWYBJK4wTYVA0%3D
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<mailto: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<mailto: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<mailto: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> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/812db320/attachment-0001.html>
On Tue Oct 20 05:30 AM, Axel Rauschmayer wrote:
The decorator proposal does not include decorators for functions, because it isn’t clear how to make them work in the face of hoisting.
What's the obsession with decorators?
Decorators are like saying everyone can decorate their Christmas trees. That's nice once a year but not when you start looking at all the different Christmas trees and have to maintain that stuff.
Suddenly the single language you thought you understood has many dialects & philosophies. Aren't embeddable languages more interesting to learn then decorated trees?
On Tue Oct 20 05:30 AM, Axel Rauschmayer wrote: > The decorator proposal does not include decorators for functions, > because it isn’t > clear how to make them work in the face of hoisting. > What's the obsession with decorators? Decorators are like saying everyone can decorate their Christmas trees. That's nice once a year but not when you start looking at all the different Christmas trees and have to maintain that stuff. Suddenly the single language you thought you understood has many dialects & philosophies. Aren't embeddable languages more interesting to learn then decorated trees?
I've become convinced by this thread that we don't need this. Other
languages where decorators are useful and prevalent don't have the
expressivity JS has, particularly regarding dynamism and function
expressions. JS class
is an awkward case due to not supporting non-method
members, but I think that is one of the actual problems that should
be solved.
Another major point I have is that most of the reasoning for decorator syntax is actually generic reasoning for paren-free function invocation à la Perl, Ruby, CoffeeScript, etc. Let's talk about that, instead of building unilateral syntax extensions into the language.
I've become convinced by this thread that we don't need this. Other languages where decorators are useful and prevalent don't have the expressivity JS has, particularly regarding dynamism and function expressions. JS `class` is an awkward case due to not supporting non-method members, but I think that is one of the actual problems that should be solved. Another major point I have is that most of the reasoning for decorator syntax is actually generic reasoning for paren-free function invocation à la Perl, Ruby, CoffeeScript, etc. Let's talk about that, instead of building unilateral syntax extensions into the language. On Tuesday, 20 October 2015, Jonathan Bond-Caron <jbondc at gdesolutions.com> wrote: > On Tue Oct 20 05:30 AM, Axel Rauschmayer wrote: > > The decorator proposal does not include decorators for functions, > > because it isn’t > > clear how to make them work in the face of hoisting. > > > > What's the obsession with decorators? > > Decorators are like saying everyone can decorate their Christmas trees. > That's nice once a year but not when you start looking at all the > different Christmas trees and have to maintain that stuff. > > Suddenly the single language you thought you understood has many dialects > & philosophies. > Aren't embeddable languages more interesting to learn then decorated trees? > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org <javascript:;> > https://mail.mozilla.org/listinfo/es-discuss > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/0140f0e8/attachment.html>
Again, everything can be defined in a similar way, actually granting those function cannot posibly be declared or redefined differently, being constants.
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
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> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151021/48d57f82/attachment-0001.html>
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:
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?)
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> >> >> >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151021/1e1d6e2d/attachment-0001.html>
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.
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> >>> >>> >>> >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151021/8626f8bf/attachment-0001.html>
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.
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/7ee6238e/attachment-0001.html>
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.
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 > <javascript:_e(%7B%7D,'cvml','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 >> <javascript:_e(%7B%7D,'cvml','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 >>> <javascript:_e(%7B%7D,'cvml','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 >> <javascript:_e(%7B%7D,'cvml','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/070172d1/attachment-0001.html>
last time I say this:
(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?
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>
Alex,
const fibonacci = memoize(function(n) {...});
this is actually a very good example that why we should let decorator do the job.
Regardless the name memoize
or memorize, whatever,
How can you tell if fibonacci is a function, a list, or just a number?
That is why we should allow decorator on function
Alex, ``` const fibonacci = memoize(function(n) {...}); ``` this is actually a very good example that why we should let decorator do the job. Regardless the name ```memoize``` or memorize, whatever, How can you tell if fibonacci is a function, a list, or just a number? That is why we should allow decorator on function -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151021/d286be84/attachment.html>
Or just use call constructor:
class F { #decorator call constructor() { ... } }
Or just use call constructor: class F { #decorator call constructor() { ... } } Rick On Tue, Oct 20, 2015 at 9:19 AM Matthew Robb <matthewwrobb at gmail.com> wrote: > Why not just do: > > ``` > const {myFunc} = { > @someDecorator; > myFunc() { > > } > }; > ``` > > > - Matthew Robb > > On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> You completely misunderstood me Bob, I don't think there's any valid use >> case for functions at all, including methods and ... .**specially** >> methods!!! >> >> I was thinking about decorators for classes, when you enrich their >> prototype in case the decorator receives a function instead of an object, >> or you enrich the object in every other case. >> >> You transform at runtime prototype methods??? Good for you, but that's >> something I'd never do, unless we are talking about lazy evaluation on the >> instance, where I don't see how lazy evaluation for an inherited method has >> anything to do with *functions* decorators. >> >> The difference is huge, methods will most likely have a `this` reference >> to be promoted on eventually, in the other case you have a function that >> unless its body has "switches" can cannot really promote much by itself and >> passing it around as higher order function that mutates? ... yak! >> >> As summary: does anyone has a valid use case for a generic function >> decorator? 'cause I still don't see one, and having decorators for any sort >> of function would be problematic in terms of code portability, which is all >> I am saying. >> >> Regards >> >> >> >> >> >> >> >> >> >> >> On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: >> >>> So wait, you agree there are valid use cases for decorating functions >>> when they are methods on an object (although I don't see much along that >>> line in the proposal). But if the function is "stand-alone" suddenly the >>> use cases evaporate? >>> >>> For example, I hack on and off on a framework involving transforming >>> functions into self-updating versions of themselves. Of course I can write >>> this as >>> >>> self_updatify(function a() { }) >>> >>> but it would be more compact and readable to say >>> >>> @self_updatify >>> function a() { } >>> >>> Which is, please correct me if I'm wrong, all decorators are about. To >>> take one example, Ember wants to use decorators not to get new >>> functionality, but to make the writing of computed properties less ugly, >>> among other reasons. (The fact that Ember makes little use of non-method >>> functions may also be one reason for the low priority placed on figuring >>> out how to decorate functions.) >>> >>> We can work to develop more examples and motivations and use cases for >>> decorated functions, although frankly it seems a little odd, as I mentioned >>> above, that there could be compelling use cases for decorated methods but >>> not for decorated functions. For the purposes of this discussion I will >>> stipulate that having decorated functions is an idea worth pursuing. If you >>> disagree, there's not point in reading further (but you might want to stop >>> and ask yourself why if it's such a great idea to have decorated methods, >>> no-one will ever want decorated functions). >>> >>> The only problem as far as I am aware is how to handle hoisting. >>> >>> AFAICS, hoisting is not an issue if the decorator has no side effects. >>> Of course there is nothing wrong with writing decorators with side effects, >>> and there are valid use cases for doing so, but they are rare. Furthermore, >>> even if a decorator does have side-effects, in only some subset of such >>> cases will the side effects together with hoisting result in unexpected >>> behavior. >>> >>> So to say that we will simply give up on decorated functions because of >>> the few cases where decorators have side effects, and those side effects >>> cause unexpected behavior due to hoisting, is really throwing out the baby >>> with the bathwater. We are telling people that you cannot decorate >>> functions at all, ever, or to decorate functions they must wrap them in a >>> class or object, because of some potentially unexpected behavior in what is >>> decidedly an edge case. >>> >>> Various proposals have been made on this topic, including hoisting >>> separately from decorating, hoisting and decorating at the same time, >>> change hoisting behavior for decorated functions, etc. etc. Each of these >>> ideas has its proponents and those who think it is the work of the devil. I >>> will not go into the details of these approaches here, and to do so is >>> actually a bit above my pay grade. >>> >>> I would just say that it is odd in the extreme that a group of >>> world-leading language designers would just throw in the towel when >>> confronted with a pretty small roadbump, instead of figuring out ways to >>> solve it. The alternative, which is to implement decorators only for >>> methods and classes and leave out functions because we couldn't figure it >>> out, seems like a major admission of failure. >>> >>> Bob >>> >>> >>> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> 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- >>>> >>>> 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 >>>>> >>>>> 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 >>>>> >>>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > _______________________________________________ > 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/20151022/33b88c72/attachment-0001.html>
One thing that seems to be missing from this thread is acknowledgement that decorators are not just simple function wrappers. They take a property descriptor as an argument, and they can return a new property descriptor - which allows an object or "class" to have its shape determined at creation time, allowing for massive engine optimization, as well as allowing for things like enumerability, configurability, writability, getters, setters, and various other metadata to be determined before the object in question is mutated, or even exists.
Decorators are certainly something that can be quasi-polyfilled, but when
applied to object or "class" properties, it allows access to the property
descriptor without needing to assign, then reflect, and then define the
resulting descriptor. @foo
isn't merely sugar for a function call without
parens - it's an imperative way to define property descriptors at object
initialization time, which is something that does not currently exist in
the language beyond get foo() {}
and set foo() {}
.
If this has been mentioned and I missed it, please ignore me, but the thread seems to have overlooked this facet of the proposal. Also, if I'm reading the proposal incorrectly, please correct me!
One thing that seems to be missing from this thread is acknowledgement that decorators are not just simple function wrappers. They take a property descriptor as an argument, and they can return a new property descriptor - which allows an object or "class" to have its shape determined at creation time, allowing for massive engine optimization, as well as allowing for things like enumerability, configurability, writability, getters, setters, and various other metadata to be determined *before the object in question is mutated, or even exists*. Decorators are certainly something that can be quasi-polyfilled, but when applied to object or "class" properties, it allows access to the property descriptor without needing to assign, then reflect, and then define the resulting descriptor. `@foo` isn't merely sugar for a function call without parens - it's an imperative way to define property descriptors at object initialization time, which is something that does not currently exist in the language beyond `get foo() {}` and `set foo() {}`. If this has been mentioned and I missed it, please ignore me, but the thread seems to have overlooked this facet of the proposal. Also, if I'm reading the proposal incorrectly, please correct me! - Jordan On Wed, Oct 21, 2015 at 7:10 PM, Rick Waldron <waldron.rick at gmail.com> wrote: > Or just use call constructor: > > class F { > #decorator > call constructor() { > ... > } > } > > > Rick > > On Tue, Oct 20, 2015 at 9:19 AM Matthew Robb <matthewwrobb at gmail.com> > wrote: > >> Why not just do: >> >> ``` >> const {myFunc} = { >> @someDecorator; >> myFunc() { >> >> } >> }; >> ``` >> >> >> - Matthew Robb >> >> On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> You completely misunderstood me Bob, I don't think there's any valid use >>> case for functions at all, including methods and ... .**specially** >>> methods!!! >>> >>> I was thinking about decorators for classes, when you enrich their >>> prototype in case the decorator receives a function instead of an object, >>> or you enrich the object in every other case. >>> >>> You transform at runtime prototype methods??? Good for you, but that's >>> something I'd never do, unless we are talking about lazy evaluation on the >>> instance, where I don't see how lazy evaluation for an inherited method has >>> anything to do with *functions* decorators. >>> >>> The difference is huge, methods will most likely have a `this` reference >>> to be promoted on eventually, in the other case you have a function that >>> unless its body has "switches" can cannot really promote much by itself and >>> passing it around as higher order function that mutates? ... yak! >>> >>> As summary: does anyone has a valid use case for a generic function >>> decorator? 'cause I still don't see one, and having decorators for any sort >>> of function would be problematic in terms of code portability, which is all >>> I am saying. >>> >>> Regards >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: >>> >>>> So wait, you agree there are valid use cases for decorating functions >>>> when they are methods on an object (although I don't see much along that >>>> line in the proposal). But if the function is "stand-alone" suddenly the >>>> use cases evaporate? >>>> >>>> For example, I hack on and off on a framework involving transforming >>>> functions into self-updating versions of themselves. Of course I can write >>>> this as >>>> >>>> self_updatify(function a() { }) >>>> >>>> but it would be more compact and readable to say >>>> >>>> @self_updatify >>>> function a() { } >>>> >>>> Which is, please correct me if I'm wrong, all decorators are about. To >>>> take one example, Ember wants to use decorators not to get new >>>> functionality, but to make the writing of computed properties less ugly, >>>> among other reasons. (The fact that Ember makes little use of non-method >>>> functions may also be one reason for the low priority placed on figuring >>>> out how to decorate functions.) >>>> >>>> We can work to develop more examples and motivations and use cases for >>>> decorated functions, although frankly it seems a little odd, as I mentioned >>>> above, that there could be compelling use cases for decorated methods but >>>> not for decorated functions. For the purposes of this discussion I will >>>> stipulate that having decorated functions is an idea worth pursuing. If you >>>> disagree, there's not point in reading further (but you might want to stop >>>> and ask yourself why if it's such a great idea to have decorated methods, >>>> no-one will ever want decorated functions). >>>> >>>> The only problem as far as I am aware is how to handle hoisting. >>>> >>>> AFAICS, hoisting is not an issue if the decorator has no side effects. >>>> Of course there is nothing wrong with writing decorators with side effects, >>>> and there are valid use cases for doing so, but they are rare. Furthermore, >>>> even if a decorator does have side-effects, in only some subset of such >>>> cases will the side effects together with hoisting result in unexpected >>>> behavior. >>>> >>>> So to say that we will simply give up on decorated functions because of >>>> the few cases where decorators have side effects, and those side effects >>>> cause unexpected behavior due to hoisting, is really throwing out the baby >>>> with the bathwater. We are telling people that you cannot decorate >>>> functions at all, ever, or to decorate functions they must wrap them in a >>>> class or object, because of some potentially unexpected behavior in what is >>>> decidedly an edge case. >>>> >>>> Various proposals have been made on this topic, including hoisting >>>> separately from decorating, hoisting and decorating at the same time, >>>> change hoisting behavior for decorated functions, etc. etc. Each of these >>>> ideas has its proponents and those who think it is the work of the devil. I >>>> will not go into the details of these approaches here, and to do so is >>>> actually a bit above my pay grade. >>>> >>>> I would just say that it is odd in the extreme that a group of >>>> world-leading language designers would just throw in the towel when >>>> confronted with a pretty small roadbump, instead of figuring out ways to >>>> solve it. The alternative, which is to implement decorators only for >>>> methods and classes and leave out functions because we couldn't figure it >>>> out, seems like a major admission of failure. >>>> >>>> Bob >>>> >>>> >>>> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >>>> andrea.giammarchi at gmail.com> wrote: >>>> >>>>> 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- >>>>> >>>>> 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 >>>>>> >>>>>> 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 >>>>>> >>>>> >>>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > _______________________________________________ > 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/d423f6a4/attachment.html>
I think the main debate here is ergonomics. And by the way, since most
descriptors simply replace the value
property (especially most that are
generic functional utilities), it could just as easily be made to deal with
both. I already make most of my descriptors that way now, so they can be
applied to either a class or function.
function descriptor(f) {
return function (target, name, desc) {
if (arguments.length < 3) return f(target)
desc.value = f(desc.value)
}
}
const memoize = descriptor(f => function () {
// stuff
})
const fibs = memoize(x =>
x < 0 ? 0 :
x <= 1 ? x :
fibs(x - 1) + fibs(x - 2))
class Foo {
@memoize
method(x) { /* ... */ }
}
My personal opinion is that the decorator looks better than function application. It also reads more clearly in that it's a function modifier, not a function simply taking a function value (like Array.prototype.map or Promise.prototype.then).
Python function decorators work similarly, IIRC.
@decorator
function memoize(f) { /* ... */ }
@memoize
function fibs(n) {
if (x < 0) return 0
if (x <= 1) return x
return fibs(x - 1) + fibs(x - 2)
}
I think the main debate here is ergonomics. And by the way, since most descriptors simply replace the `value` property (especially most that are generic functional utilities), it could just as easily be made to deal with both. I already make most of my descriptors that way now, so they can be applied to either a class or function. ```js function descriptor(f) { return function (target, name, desc) { if (arguments.length < 3) return f(target) desc.value = f(desc.value) } } const memoize = descriptor(f => function () { // stuff }) const fibs = memoize(x => x < 0 ? 0 : x <= 1 ? x : fibs(x - 1) + fibs(x - 2)) class Foo { @memoize method(x) { /* ... */ } } ``` My personal opinion is that the decorator looks better than function application. It also reads more clearly in that it's a function modifier, not a function simply taking a function value (like Array.prototype.map or Promise.prototype.then). Python function decorators work similarly, IIRC. ```js @decorator function memoize(f) { /* ... */ } @memoize function fibs(n) { if (x < 0) return 0 if (x <= 1) return x return fibs(x - 1) + fibs(x - 2) } ``` On Thu, Oct 22, 2015, 00:34 Jordan Harband <ljharb at gmail.com> wrote: > One thing that seems to be missing from this thread is acknowledgement > that decorators are not just simple function wrappers. They take a property > descriptor as an argument, and they can return a new property descriptor - > which allows an object or "class" to have its shape determined at creation > time, allowing for massive engine optimization, as well as allowing for > things like enumerability, configurability, writability, getters, setters, > and various other metadata to be determined *before the object in question > is mutated, or even exists*. > > Decorators are certainly something that can be quasi-polyfilled, but when > applied to object or "class" properties, it allows access to the property > descriptor without needing to assign, then reflect, and then define the > resulting descriptor. `@foo` isn't merely sugar for a function call without > parens - it's an imperative way to define property descriptors at object > initialization time, which is something that does not currently exist in > the language beyond `get foo() {}` and `set foo() {}`. > > If this has been mentioned and I missed it, please ignore me, but the > thread seems to have overlooked this facet of the proposal. Also, if I'm > reading the proposal incorrectly, please correct me! > > - Jordan > > On Wed, Oct 21, 2015 at 7:10 PM, Rick Waldron <waldron.rick at gmail.com> > wrote: > >> Or just use call constructor: >> >> class F { >> #decorator >> call constructor() { >> ... >> } >> } >> >> >> Rick >> >> On Tue, Oct 20, 2015 at 9:19 AM Matthew Robb <matthewwrobb at gmail.com> >> wrote: >> >>> Why not just do: >>> >>> ``` >>> const {myFunc} = { >>> @someDecorator; >>> myFunc() { >>> >>> } >>> }; >>> ``` >>> >>> >>> - Matthew Robb >>> >>> On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> You completely misunderstood me Bob, I don't think there's any valid >>>> use case for functions at all, including methods and ... .**specially** >>>> methods!!! >>>> >>>> I was thinking about decorators for classes, when you enrich their >>>> prototype in case the decorator receives a function instead of an object, >>>> or you enrich the object in every other case. >>>> >>>> You transform at runtime prototype methods??? Good for you, but that's >>>> something I'd never do, unless we are talking about lazy evaluation on the >>>> instance, where I don't see how lazy evaluation for an inherited method has >>>> anything to do with *functions* decorators. >>>> >>>> The difference is huge, methods will most likely have a `this` >>>> reference to be promoted on eventually, in the other case you have a >>>> function that unless its body has "switches" can cannot really promote much >>>> by itself and passing it around as higher order function that mutates? ... >>>> yak! >>>> >>>> As summary: does anyone has a valid use case for a generic function >>>> decorator? 'cause I still don't see one, and having decorators for any sort >>>> of function would be problematic in terms of code portability, which is all >>>> I am saying. >>>> >>>> Regards >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: >>>> >>>>> So wait, you agree there are valid use cases for decorating functions >>>>> when they are methods on an object (although I don't see much along that >>>>> line in the proposal). But if the function is "stand-alone" suddenly the >>>>> use cases evaporate? >>>>> >>>>> For example, I hack on and off on a framework involving transforming >>>>> functions into self-updating versions of themselves. Of course I can write >>>>> this as >>>>> >>>>> self_updatify(function a() { }) >>>>> >>>>> but it would be more compact and readable to say >>>>> >>>>> @self_updatify >>>>> function a() { } >>>>> >>>>> Which is, please correct me if I'm wrong, all decorators are about. To >>>>> take one example, Ember wants to use decorators not to get new >>>>> functionality, but to make the writing of computed properties less ugly, >>>>> among other reasons. (The fact that Ember makes little use of non-method >>>>> functions may also be one reason for the low priority placed on figuring >>>>> out how to decorate functions.) >>>>> >>>>> We can work to develop more examples and motivations and use cases for >>>>> decorated functions, although frankly it seems a little odd, as I mentioned >>>>> above, that there could be compelling use cases for decorated methods but >>>>> not for decorated functions. For the purposes of this discussion I will >>>>> stipulate that having decorated functions is an idea worth pursuing. If you >>>>> disagree, there's not point in reading further (but you might want to stop >>>>> and ask yourself why if it's such a great idea to have decorated methods, >>>>> no-one will ever want decorated functions). >>>>> >>>>> The only problem as far as I am aware is how to handle hoisting. >>>>> >>>>> AFAICS, hoisting is not an issue if the decorator has no side effects. >>>>> Of course there is nothing wrong with writing decorators with side effects, >>>>> and there are valid use cases for doing so, but they are rare. Furthermore, >>>>> even if a decorator does have side-effects, in only some subset of such >>>>> cases will the side effects together with hoisting result in unexpected >>>>> behavior. >>>>> >>>>> So to say that we will simply give up on decorated functions because >>>>> of the few cases where decorators have side effects, and those side effects >>>>> cause unexpected behavior due to hoisting, is really throwing out the baby >>>>> with the bathwater. We are telling people that you cannot decorate >>>>> functions at all, ever, or to decorate functions they must wrap them in a >>>>> class or object, because of some potentially unexpected behavior in what is >>>>> decidedly an edge case. >>>>> >>>>> Various proposals have been made on this topic, including hoisting >>>>> separately from decorating, hoisting and decorating at the same time, >>>>> change hoisting behavior for decorated functions, etc. etc. Each of these >>>>> ideas has its proponents and those who think it is the work of the devil. I >>>>> will not go into the details of these approaches here, and to do so is >>>>> actually a bit above my pay grade. >>>>> >>>>> I would just say that it is odd in the extreme that a group of >>>>> world-leading language designers would just throw in the towel when >>>>> confronted with a pretty small roadbump, instead of figuring out ways to >>>>> solve it. The alternative, which is to implement decorators only for >>>>> methods and classes and leave out functions because we couldn't figure it >>>>> out, seems like a major admission of failure. >>>>> >>>>> Bob >>>>> >>>>> >>>>> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >>>>> andrea.giammarchi at gmail.com> wrote: >>>>> >>>>>> 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- >>>>>> >>>>>> 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 >>>>>>> >>>>>>> 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 >>>>>>> >>>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > _______________________________________________ > 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/20151022/2e512839/attachment.html>
OK, appreciate that. Let's explore this problem space: Why not have syntax to set a property descriptor onto a class or object literal?
In Python, this is implicit. For example (IIRC):
class Foo:
prop = some_descriptor
x = 100
Both Foo.x
and Foo().x
(instance attribute access) have the value
100
, but assuming some_descriptor
has __get__
, __set__
,
__delete__
methods, then accessing prop
on an instance will magically
use these descriptor methods. Obviously an issue here is that you might
literally have wanted the prop
attribute's value to be this actual
descriptor object, so IMO something explicit for this is better in JS.
Let's instead imagine that @ is used to activate descriptor setting:
const myObj = {
prop: @someDescriptorExpression,
};
// e.g.
const myObj = {
prop: @{value: whatever, writable: false},
};
Now clearly "decorators" like readonly
are just function application.
Even defining a get/set pair for a property is straightforward:
const readonly = v => {value: v, writable: false};
const myObj = {
prop: @readonly(whatever),
answer: @readonly(42),
x: @{
get() { return this.answer(); }
set(x) { throw new Error("nope"); }
}
};
"Decorators" like memoize
are still just in terms of functions and
don't require this syntax -- memoizing something should never be in terms
of descriptors because it has zero interest in property descriptors (why
should memoize
make a call on whether the returned function is an
enumerable, or writable, etc.?)
const fib = memoize(x => {
// ...
});
ES6 class issues are IMO an orthogonal issue to be solved:
class Foo {
x: 100 // lots and lots of questions here...
}
OK, appreciate that. Let's explore this problem space: Why not have syntax to set a property descriptor onto a class or object literal? In Python, this is implicit. For example (IIRC): ```python class Foo: prop = some_descriptor x = 100 ``` Both `Foo.x` and `Foo().x` (instance attribute access) have the value `100`, but assuming `some_descriptor` has `__get__`, `__set__`, `__delete__` methods, then accessing `prop` on an instance will magically use these descriptor methods. Obviously an issue here is that you might literally have wanted the `prop` attribute's value to be this actual descriptor object, so IMO something explicit for this is better in JS. Let's instead imagine that @ is used to activate descriptor setting: ```js const myObj = { prop: @someDescriptorExpression, }; // e.g. const myObj = { prop: @{value: whatever, writable: false}, }; ``` Now clearly "decorators" like `readonly` are just function application. Even defining a get/set pair for a property is straightforward: ```js const readonly = v => {value: v, writable: false}; const myObj = { prop: @readonly(whatever), answer: @readonly(42), x: @{ get() { return this.answer(); } set(x) { throw new Error("nope"); } } }; ``` "Decorators" like `memoize` are *still just in terms of functions* and don't require this syntax -- memoizing something should never be in terms of descriptors because it has *zero* interest in property descriptors (why should `memoize` make a call on whether the returned function is an enumerable, or writable, etc.?) ```js const fib = memoize(x => { // ... }); ``` ES6 class issues are IMO an orthogonal issue to be solved: ```js class Foo { x: 100 // lots and lots of questions here... } ``` On 22 October 2015 at 05:34, Jordan Harband <ljharb at gmail.com> wrote: > One thing that seems to be missing from this thread is acknowledgement > that decorators are not just simple function wrappers. They take a property > descriptor as an argument, and they can return a new property descriptor - > which allows an object or "class" to have its shape determined at creation > time, allowing for massive engine optimization, as well as allowing for > things like enumerability, configurability, writability, getters, setters, > and various other metadata to be determined *before the object in question > is mutated, or even exists*. > > Decorators are certainly something that can be quasi-polyfilled, but when > applied to object or "class" properties, it allows access to the property > descriptor without needing to assign, then reflect, and then define the > resulting descriptor. `@foo` isn't merely sugar for a function call without > parens - it's an imperative way to define property descriptors at object > initialization time, which is something that does not currently exist in > the language beyond `get foo() {}` and `set foo() {}`. > > If this has been mentioned and I missed it, please ignore me, but the > thread seems to have overlooked this facet of the proposal. Also, if I'm > reading the proposal incorrectly, please correct me! > > - Jordan > > On Wed, Oct 21, 2015 at 7:10 PM, Rick Waldron <waldron.rick at gmail.com> > wrote: > >> Or just use call constructor: >> >> class F { >> #decorator >> call constructor() { >> ... >> } >> } >> >> >> Rick >> >> On Tue, Oct 20, 2015 at 9:19 AM Matthew Robb <matthewwrobb at gmail.com> >> wrote: >> >>> Why not just do: >>> >>> ``` >>> const {myFunc} = { >>> @someDecorator; >>> myFunc() { >>> >>> } >>> }; >>> ``` >>> >>> >>> - Matthew Robb >>> >>> On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> You completely misunderstood me Bob, I don't think there's any valid >>>> use case for functions at all, including methods and ... .**specially** >>>> methods!!! >>>> >>>> I was thinking about decorators for classes, when you enrich their >>>> prototype in case the decorator receives a function instead of an object, >>>> or you enrich the object in every other case. >>>> >>>> You transform at runtime prototype methods??? Good for you, but that's >>>> something I'd never do, unless we are talking about lazy evaluation on the >>>> instance, where I don't see how lazy evaluation for an inherited method has >>>> anything to do with *functions* decorators. >>>> >>>> The difference is huge, methods will most likely have a `this` >>>> reference to be promoted on eventually, in the other case you have a >>>> function that unless its body has "switches" can cannot really promote much >>>> by itself and passing it around as higher order function that mutates? ... >>>> yak! >>>> >>>> As summary: does anyone has a valid use case for a generic function >>>> decorator? 'cause I still don't see one, and having decorators for any sort >>>> of function would be problematic in terms of code portability, which is all >>>> I am saying. >>>> >>>> Regards >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: >>>> >>>>> So wait, you agree there are valid use cases for decorating functions >>>>> when they are methods on an object (although I don't see much along that >>>>> line in the proposal). But if the function is "stand-alone" suddenly the >>>>> use cases evaporate? >>>>> >>>>> For example, I hack on and off on a framework involving transforming >>>>> functions into self-updating versions of themselves. Of course I can write >>>>> this as >>>>> >>>>> self_updatify(function a() { }) >>>>> >>>>> but it would be more compact and readable to say >>>>> >>>>> @self_updatify >>>>> function a() { } >>>>> >>>>> Which is, please correct me if I'm wrong, all decorators are about. To >>>>> take one example, Ember wants to use decorators not to get new >>>>> functionality, but to make the writing of computed properties less ugly, >>>>> among other reasons. (The fact that Ember makes little use of non-method >>>>> functions may also be one reason for the low priority placed on figuring >>>>> out how to decorate functions.) >>>>> >>>>> We can work to develop more examples and motivations and use cases for >>>>> decorated functions, although frankly it seems a little odd, as I mentioned >>>>> above, that there could be compelling use cases for decorated methods but >>>>> not for decorated functions. For the purposes of this discussion I will >>>>> stipulate that having decorated functions is an idea worth pursuing. If you >>>>> disagree, there's not point in reading further (but you might want to stop >>>>> and ask yourself why if it's such a great idea to have decorated methods, >>>>> no-one will ever want decorated functions). >>>>> >>>>> The only problem as far as I am aware is how to handle hoisting. >>>>> >>>>> AFAICS, hoisting is not an issue if the decorator has no side effects. >>>>> Of course there is nothing wrong with writing decorators with side effects, >>>>> and there are valid use cases for doing so, but they are rare. Furthermore, >>>>> even if a decorator does have side-effects, in only some subset of such >>>>> cases will the side effects together with hoisting result in unexpected >>>>> behavior. >>>>> >>>>> So to say that we will simply give up on decorated functions because >>>>> of the few cases where decorators have side effects, and those side effects >>>>> cause unexpected behavior due to hoisting, is really throwing out the baby >>>>> with the bathwater. We are telling people that you cannot decorate >>>>> functions at all, ever, or to decorate functions they must wrap them in a >>>>> class or object, because of some potentially unexpected behavior in what is >>>>> decidedly an edge case. >>>>> >>>>> Various proposals have been made on this topic, including hoisting >>>>> separately from decorating, hoisting and decorating at the same time, >>>>> change hoisting behavior for decorated functions, etc. etc. Each of these >>>>> ideas has its proponents and those who think it is the work of the devil. I >>>>> will not go into the details of these approaches here, and to do so is >>>>> actually a bit above my pay grade. >>>>> >>>>> I would just say that it is odd in the extreme that a group of >>>>> world-leading language designers would just throw in the towel when >>>>> confronted with a pretty small roadbump, instead of figuring out ways to >>>>> solve it. The alternative, which is to implement decorators only for >>>>> methods and classes and leave out functions because we couldn't figure it >>>>> out, seems like a major admission of failure. >>>>> >>>>> Bob >>>>> >>>>> >>>>> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >>>>> andrea.giammarchi at gmail.com> wrote: >>>>> >>>>>> 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- >>>>>> >>>>>> 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 >>>>>>> >>>>>>> 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 >>>>>>> >>>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > _______________________________________________ > 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/20151022/9b5c5b63/attachment-0001.html>
Agred with Jordan and it's basically what I've said since the beginning. Decorators with target and descriptors are fine and works well, you drop targets and descriptors from the equation, it's an ugly mess that canno be ported and every decorator will magically decide if it should work with a class rather than a function.
Maybe for functions only we need something else, which might work as well. @@ or @() or @::meomize or something
Agred with Jordan and it's basically what I've said since the beginning. Decorators with target and descriptors are fine and works well, you drop targets and descriptors from the equation, it's an ugly mess that canno be ported and every decorator will magically decide if it should work with a class rather than a function. Maybe for functions only we need something else, which might work as well. @@ or @() or @::meomize or something On Thu, Oct 22, 2015 at 5:34 AM, Jordan Harband <ljharb at gmail.com> wrote: > One thing that seems to be missing from this thread is acknowledgement > that decorators are not just simple function wrappers. They take a property > descriptor as an argument, and they can return a new property descriptor - > which allows an object or "class" to have its shape determined at creation > time, allowing for massive engine optimization, as well as allowing for > things like enumerability, configurability, writability, getters, setters, > and various other metadata to be determined *before the object in question > is mutated, or even exists*. > > Decorators are certainly something that can be quasi-polyfilled, but when > applied to object or "class" properties, it allows access to the property > descriptor without needing to assign, then reflect, and then define the > resulting descriptor. `@foo` isn't merely sugar for a function call without > parens - it's an imperative way to define property descriptors at object > initialization time, which is something that does not currently exist in > the language beyond `get foo() {}` and `set foo() {}`. > > If this has been mentioned and I missed it, please ignore me, but the > thread seems to have overlooked this facet of the proposal. Also, if I'm > reading the proposal incorrectly, please correct me! > > - Jordan > > On Wed, Oct 21, 2015 at 7:10 PM, Rick Waldron <waldron.rick at gmail.com> > wrote: > >> Or just use call constructor: >> >> class F { >> #decorator >> call constructor() { >> ... >> } >> } >> >> >> Rick >> >> On Tue, Oct 20, 2015 at 9:19 AM Matthew Robb <matthewwrobb at gmail.com> >> wrote: >> >>> Why not just do: >>> >>> ``` >>> const {myFunc} = { >>> @someDecorator; >>> myFunc() { >>> >>> } >>> }; >>> ``` >>> >>> >>> - Matthew Robb >>> >>> On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> You completely misunderstood me Bob, I don't think there's any valid >>>> use case for functions at all, including methods and ... .**specially** >>>> methods!!! >>>> >>>> I was thinking about decorators for classes, when you enrich their >>>> prototype in case the decorator receives a function instead of an object, >>>> or you enrich the object in every other case. >>>> >>>> You transform at runtime prototype methods??? Good for you, but that's >>>> something I'd never do, unless we are talking about lazy evaluation on the >>>> instance, where I don't see how lazy evaluation for an inherited method has >>>> anything to do with *functions* decorators. >>>> >>>> The difference is huge, methods will most likely have a `this` >>>> reference to be promoted on eventually, in the other case you have a >>>> function that unless its body has "switches" can cannot really promote much >>>> by itself and passing it around as higher order function that mutates? ... >>>> yak! >>>> >>>> As summary: does anyone has a valid use case for a generic function >>>> decorator? 'cause I still don't see one, and having decorators for any sort >>>> of function would be problematic in terms of code portability, which is all >>>> I am saying. >>>> >>>> Regards >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <rtm at gol.com> wrote: >>>> >>>>> So wait, you agree there are valid use cases for decorating functions >>>>> when they are methods on an object (although I don't see much along that >>>>> line in the proposal). But if the function is "stand-alone" suddenly the >>>>> use cases evaporate? >>>>> >>>>> For example, I hack on and off on a framework involving transforming >>>>> functions into self-updating versions of themselves. Of course I can write >>>>> this as >>>>> >>>>> self_updatify(function a() { }) >>>>> >>>>> but it would be more compact and readable to say >>>>> >>>>> @self_updatify >>>>> function a() { } >>>>> >>>>> Which is, please correct me if I'm wrong, all decorators are about. To >>>>> take one example, Ember wants to use decorators not to get new >>>>> functionality, but to make the writing of computed properties less ugly, >>>>> among other reasons. (The fact that Ember makes little use of non-method >>>>> functions may also be one reason for the low priority placed on figuring >>>>> out how to decorate functions.) >>>>> >>>>> We can work to develop more examples and motivations and use cases for >>>>> decorated functions, although frankly it seems a little odd, as I mentioned >>>>> above, that there could be compelling use cases for decorated methods but >>>>> not for decorated functions. For the purposes of this discussion I will >>>>> stipulate that having decorated functions is an idea worth pursuing. If you >>>>> disagree, there's not point in reading further (but you might want to stop >>>>> and ask yourself why if it's such a great idea to have decorated methods, >>>>> no-one will ever want decorated functions). >>>>> >>>>> The only problem as far as I am aware is how to handle hoisting. >>>>> >>>>> AFAICS, hoisting is not an issue if the decorator has no side effects. >>>>> Of course there is nothing wrong with writing decorators with side effects, >>>>> and there are valid use cases for doing so, but they are rare. Furthermore, >>>>> even if a decorator does have side-effects, in only some subset of such >>>>> cases will the side effects together with hoisting result in unexpected >>>>> behavior. >>>>> >>>>> So to say that we will simply give up on decorated functions because >>>>> of the few cases where decorators have side effects, and those side effects >>>>> cause unexpected behavior due to hoisting, is really throwing out the baby >>>>> with the bathwater. We are telling people that you cannot decorate >>>>> functions at all, ever, or to decorate functions they must wrap them in a >>>>> class or object, because of some potentially unexpected behavior in what is >>>>> decidedly an edge case. >>>>> >>>>> Various proposals have been made on this topic, including hoisting >>>>> separately from decorating, hoisting and decorating at the same time, >>>>> change hoisting behavior for decorated functions, etc. etc. Each of these >>>>> ideas has its proponents and those who think it is the work of the devil. I >>>>> will not go into the details of these approaches here, and to do so is >>>>> actually a bit above my pay grade. >>>>> >>>>> I would just say that it is odd in the extreme that a group of >>>>> world-leading language designers would just throw in the towel when >>>>> confronted with a pretty small roadbump, instead of figuring out ways to >>>>> solve it. The alternative, which is to implement decorators only for >>>>> methods and classes and leave out functions because we couldn't figure it >>>>> out, seems like a major admission of failure. >>>>> >>>>> Bob >>>>> >>>>> >>>>> On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi < >>>>> andrea.giammarchi at gmail.com> wrote: >>>>> >>>>>> 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- >>>>>> >>>>>> 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 >>>>>>> >>>>>>> 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 >>>>>>> >>>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> >> _______________________________________________ >> 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/20151022/60ae9c20/attachment.html>
On 22 October 2015 at 06:34, Jordan Harband <ljharb at gmail.com> wrote:
One thing that seems to be missing from this thread is acknowledgement that decorators are not just simple function wrappers. They take a property descriptor as an argument, and they can return a new property descriptor - which allows an object or "class" to have its shape determined at creation time, allowing for massive engine optimization,
Er. I don't know where this myth is coming from, but let me debunk it right there:
Decorators do not enable optimisations. If anything, they prevent optimisations.
What enables optimisations is a more declarative semantics with more invariants, less mutation, less reflection, and less intercession. That was one significant advantage of class syntax over previous imperative JS patterns.
Decorators pretty much revert that (hard-fought) progress, because despite their looks, they are all but declarative, and just as imperative as the old-style patterns. Or function wrappers. A class that uses decorators will very likely have to go through all the same (or even worse) runtime overhead.
On 22 October 2015 at 06:34, Jordan Harband <ljharb at gmail.com> wrote: > One thing that seems to be missing from this thread is acknowledgement that > decorators are not just simple function wrappers. They take a property > descriptor as an argument, and they can return a new property descriptor - > which allows an object or "class" to have its shape determined at creation > time, allowing for massive engine optimization, Er. I don't know where this myth is coming from, but let me debunk it right there: Decorators do not enable optimisations. If anything, they _prevent_ optimisations. What enables optimisations is a more declarative semantics with more invariants, less mutation, less reflection, and less intercession. That was one significant advantage of class syntax over previous imperative JS patterns. Decorators pretty much revert that (hard-fought) progress, because despite their looks, they are all but declarative, and just as imperative as the old-style patterns. Or function wrappers. A class that uses decorators will very likely have to go through all the same (or even worse) runtime overhead. /Andreas
On Thu Oct 22 07:44 AM, Andreas Rossberg wrote:
determined at creation time, allowing for massive engine optimization,
Ya I'm not sure from which hat "massive engine optimization" comes from?
What's meant is likely using decorators as annotations (compile time optimizations hints): www.google.com/patents/US7013458
Or 'ambient decorators': jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators
There's 2 patterns (maybe more?): (a) Tagging a 'tree transformation' on a node. (b) Metadata at compile time on a node.
The thing about (b) is it can easily live outside of the code (like in typescript where you have an optional header/declaration file)
With (a), it seems more conservative to see how it gets used with classes before bolting on to functions (opinion: end result in java is not something to be proud of).
On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: > > determined at creation time, allowing for massive engine optimization, > Ya I'm not sure from which hat "massive engine optimization" comes from? What's meant is likely using decorators as annotations (compile time optimizations hints): http://www.google.com/patents/US7013458 Or 'ambient decorators': https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators There's 2 patterns (maybe more?): (a) Tagging a 'tree transformation' on a node. (b) Metadata at compile time on a node. The thing about (b) is it can easily live outside of the code (like in typescript where you have an optional header/declaration file) With (a), it seems more conservative to see how it gets used with classes before bolting on to functions (opinion: end result in java is not something to be proud of).
Andreas, thanks for correcting me on the optimization angle. I've been under that impression for awhile.
Are you saying that to achieve the optimization I envision, we'd need declarative syntax for descriptor properties (like enumerability etc), rather than function calls? or would that also prevent optimizations?
Andreas, thanks for correcting me on the optimization angle. I've been under that impression for awhile. Are you saying that to achieve the optimization I envision, we'd need declarative syntax for descriptor properties (like enumerability etc), rather than function calls? or would that also prevent optimizations? On Thu, Oct 22, 2015 at 9:20 AM, Jonathan Bond-Caron < jbondc at gdesolutions.com> wrote: > On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: > > > determined at creation time, allowing for massive engine optimization, > > > > Ya I'm not sure from which hat "massive engine optimization" comes from? > > What's meant is likely using decorators as annotations (compile time > optimizations hints): > http://www.google.com/patents/US7013458 > > Or 'ambient decorators': > > https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators > > There's 2 patterns (maybe more?): > (a) Tagging a 'tree transformation' on a node. > (b) Metadata at compile time on a node. > > The thing about (b) is it can easily live outside of the code (like in > typescript where you have an optional header/declaration file) > > With (a), it seems more conservative to see how it gets used with classes > before bolting on to functions (opinion: end result in java is not > something to be proud of). > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151022/36fbd37e/attachment.html>
I don't think
@@ or @() or @::meomize
would really help much, you can tell what the decorator does by simply looking at its name. And looks like you can not use @ and @@ for the same decorator function without adding extra condition checking inside the function.
There are two patterns that we have discussed here, they are actually quite distinct. I still think we should support decorator on variables, but maybe we should have 2 distinct syntax for the normal decorators and "ambient decorators"(from Jonathan's post):
-
decorator that alter the code behavior, the currently proposed decorator. Such as
@memoize
-
decorator that absolutely does not alter the code behavior, only used for optimization, checking or debugging. Instead of @, a distinct syntax will be much clearer ex.
@annotatition@
(Maybe it should be called annotation instead?):
@deprecated@
@number,number=>string@/*type checking*/
@debug("this message will only print in development mode")@
it sounds like terrible idea to have a decorator in code that you can not figure out if it will alter the code behavior by looking at it. I do like to see all the new ideas been added into javascript, but it is also necessary to eliminate the ambiguity whenever possible.
I don't think > ```@@ or @() or @::meomize``` would really help much, you can tell what the decorator does by simply looking at its name. And looks like you can not use @ and @@ for the same decorator function without adding extra condition checking inside the function. There are two patterns that we have discussed here, they are actually quite distinct. I still think we should support decorator on variables, but maybe we should have 2 distinct syntax for the normal decorators and "ambient decorators"(from Jonathan's post): 1. decorator that alter the code behavior, the currently proposed decorator. Such as ```@memoize``` 2. decorator that absolutely does not alter the code behavior, only used for optimization, checking or debugging. Instead of @, a distinct syntax will be much clearer ex.```@annotatition@``` (Maybe it should be called annotation instead?): ``` @deprecated@ @number,number=>string@/*type checking*/ @debug("this message will only print in development mode")@ ``` it sounds like terrible idea to have a decorator in code that you can not figure out if it will alter the code behavior by looking at it. I do like to see all the new ideas been added into javascript, but it is also necessary to eliminate the ambiguity whenever possible. On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < jbondc at gdesolutions.com> wrote: > On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: > > > determined at creation time, allowing for massive engine optimization, > > > > Ya I'm not sure from which hat "massive engine optimization" comes from? > > What's meant is likely using decorators as annotations (compile time > optimizations hints): > http://www.google.com/patents/US7013458 > > Or 'ambient decorators': > > https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators > > There's 2 patterns (maybe more?): > (a) Tagging a 'tree transformation' on a node. > (b) Metadata at compile time on a node. > > The thing about (b) is it can easily live outside of the code (like in > typescript where you have an optional header/declaration file) > > With (a), it seems more conservative to see how it gets used with classes > before bolting on to functions (opinion: end result in java is not > something to be proud of). > > _______________________________________________ > 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/20151022/3fa2d3d9/attachment.html>
Removing ambiguity is my point since the very first post: current proposal is about a target, a property name, and a descriptor for such property ... having functions/variables decorators have no target (in strict mode undefined can't be a target, right?) and not necessarily a descriptor, or if any, always a data one with fields that makes no sense (like enumerable within a private scope ... what does that even mean)
I'm all in for a distinct, separate, syntax to decorate "callables" or other variables as long as the current proposal will make for ES7 and won't be bothered by this different requirement.
Removing ambiguity is my point since the very first post: current proposal is about a target, a property name, and a descriptor for such property ... having functions/variables decorators have no target (in strict mode undefined can't be a target, right?) and not necessarily a descriptor, or if any, always a data one with fields that makes no sense (like enumerable within a private scope ... what does that even mean) I'm all in for a distinct, separate, syntax to decorate "callables" or other variables as long as the current proposal will make for ES7 and won't be bothered by this different requirement. Regards On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> wrote: > I don't think > > > ```@@ or @() or @::meomize``` > > would really help much, you can tell what the decorator does by simply > looking at its name. And looks like you can not use @ and @@ for the same decorator function > without adding extra condition checking inside the function. > > There are two patterns that we have discussed here, they are actually > quite distinct. I still think we should support decorator on variables, but > maybe we should have 2 distinct syntax for the normal decorators and "ambient > decorators"(from Jonathan's post): > > 1. decorator that alter the code behavior, the currently proposed > decorator. Such as ```@memoize``` > > 2. decorator that absolutely does not alter the code behavior, only used > for optimization, checking or debugging. Instead of @, a distinct syntax > will be much clearer ex.```@annotatition@``` (Maybe it should be called > annotation instead?): > ``` > @deprecated@ > > @number,number=>string@/*type checking*/ > > @debug("this message will only print in development mode")@ > ``` > > it sounds like terrible idea to have a decorator in code that you can not > figure out if it will alter the code behavior by looking at it. I do like > to see all the new ideas been added into javascript, but it is also > necessary to eliminate the ambiguity whenever possible. > > > On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < > jbondc at gdesolutions.com> wrote: > >> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >> > > determined at creation time, allowing for massive engine optimization, >> > >> >> Ya I'm not sure from which hat "massive engine optimization" comes from? >> >> What's meant is likely using decorators as annotations (compile time >> optimizations hints): >> http://www.google.com/patents/US7013458 >> >> Or 'ambient decorators': >> >> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >> >> There's 2 patterns (maybe more?): >> (a) Tagging a 'tree transformation' on a node. >> (b) Metadata at compile time on a node. >> >> The thing about (b) is it can easily live outside of the code (like in >> typescript where you have an optional header/declaration file) >> >> With (a), it seems more conservative to see how it gets used with classes >> before bolting on to functions (opinion: end result in java is not >> something to be proud of). >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > _______________________________________________ > 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/20151022/a941375b/attachment-0001.html>
Andrea,
Is your concern about disambiguating the usage of a decorator at the call site or within the body of the decorator? In the current proposal, you can decorate a class member, or the class itself.
When decorating a class member, three arguments are passed to the decorator: The target, the property key (string or symbol), and the descriptor. When decorating the class, one argument is passed to the decorator: The constructor function. Generally this means that you can disambiguate the usage of the decorator based simply on arguments.length
, or testing for undefined
for the property key or descriptor.
Would it be better to have a more consistent way to disambiguate the usage of a decorator from within the decorator? This could be addressed with something like a Reflect.getDecoratorUsage API or a function.decoration
meta-property or the like. Consider something like:
function memoize(target, key, descriptor) {
switch (Reflect.getDecoratorUsage(arguments)) {
case "class":
// `target` is the class constructor. `key` and `descriptor` are undefined.
case "function":
// `target` is the function. `key` and `descriptor` are undefined.
case "method":
// `target` is the object containing the method (e.g. constructor
// for a static method, prototype for a prototype method, or
// instance for an object literal method).
// `key` is the string or symbol property name for the method.
// `descriptor` is the property descriptor for the method.
case "accessor":
// `target` is the object containing the accessor (e.g. constructor
// for a static accessor, prototype for a prototype accessor, or
// instance for an object literal accessor).
// `key` is the string or symbol property name for the accessor.
// `descriptor` is the property descriptor for the accessor.
}
}
Ron
From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Andrea Giammarchi Sent: Thursday, October 22, 2015 10:47 AM To: Yongxu Ren <renyongxu at gmail.com>
Cc: es-discuss mailing list <es-discuss at mozilla.org>
Subject: Re: Decorators for functions
Removing ambiguity is my point since the very first post: current proposal is about a target, a property name, and a descriptor for such property ... having functions/variables decorators have no target (in strict mode undefined can't be a target, right?) and not necessarily a descriptor, or if any, always a data one with fields that makes no sense (like enumerable within a private scope ... what does that even mean)
I'm all in for a distinct, separate, syntax to decorate "callables" or other variables as long as the current proposal will make for ES7 and won't be bothered by this different requirement.
On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com<mailto:renyongxu at gmail.com>> wrote:
I don't think
@@ or @() or @::meomize
would really help much, you can tell what the decorator does by simply looking at its name. And looks like you can not use @ and @@ for the same decorator function without adding extra condition checking inside the function.
There are two patterns that we have discussed here, they are actually quite distinct. I still think we should support decorator on variables, but maybe we should have 2 distinct syntax for the normal decorators and "ambient decorators"(from Jonathan's post):
-
decorator that alter the code behavior, the currently proposed decorator. Such as
@memoize
-
decorator that absolutely does not alter the code behavior, only used for optimization, checking or debugging. Instead of @, a distinct syntax will be much clearer ex.
@annotatition@
(Maybe it should be called annotation instead?):
@deprecated@
@number,number=>string@/*type checking*/
@debug("this message will only print in development mode")@
it sounds like terrible idea to have a decorator in code that you can not figure out if it will alter the code behavior by looking at it. I do like to see all the new ideas been added into javascript, but it is also necessary to eliminate the ambiguity whenever possible.
On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron <jbondc at gdesolutions.com<mailto:jbondc at gdesolutions.com>> wrote:
On Thu Oct 22 07:44 AM, Andreas Rossberg wrote:
determined at creation time, allowing for massive engine optimization,
Ya I'm not sure from which hat "massive engine optimization" comes from?
What's meant is likely using decorators as annotations (compile time optimizations hints): www.google.com/patents/US7013458na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.google.com%2Fpatents%2FUS7013458&data=01|01|ron.buckton%40microsoft.com|4f28552d1837468197db08d2db08dcea|72f988bf86f141af91ab2d7cd011db47|1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3D
Or 'ambient decorators': jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decoratorsna01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fjonathandturner%2Fbrainstorming%2Fblob%2Fmaster%2FREADME.md%23c6-ambient-decorators&data=01|01|ron.buckton%40microsoft.com|4f28552d1837468197db08d2db08dcea|72f988bf86f141af91ab2d7cd011db47|1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3D
There's 2 patterns (maybe more?): (a) Tagging a 'tree transformation' on a node. (b) Metadata at compile time on a node.
The thing about (b) is it can easily live outside of the code (like in typescript where you have an optional header/declaration file)
With (a), it seems more conservative to see how it gets used with classes before bolting on to functions (opinion: end result in java is not something to be proud of).
Andrea, Is your concern about disambiguating the usage of a decorator at the call site or within the body of the decorator? In the current proposal, you can decorate a class member, or the class itself. When decorating a class member, three arguments are passed to the decorator: The target, the property key (string or symbol), and the descriptor. When decorating the class, one argument is passed to the decorator: The constructor function. Generally this means that you can disambiguate the usage of the decorator based simply on `arguments.length`, or testing for `undefined` for the property key or descriptor. Would it be better to have a more consistent way to disambiguate the usage of a decorator from within the decorator? This could be addressed with something like a Reflect.getDecoratorUsage API or a `function.decoration` meta-property or the like. Consider something like: ```js function memoize(target, key, descriptor) { switch (Reflect.getDecoratorUsage(arguments)) { case "class": // `target` is the class constructor. `key` and `descriptor` are undefined. case "function": // `target` is the function. `key` and `descriptor` are undefined. case "method": // `target` is the object containing the method (e.g. constructor // for a static method, prototype for a prototype method, or // instance for an object literal method). // `key` is the string or symbol property name for the method. // `descriptor` is the property descriptor for the method. case "accessor": // `target` is the object containing the accessor (e.g. constructor // for a static accessor, prototype for a prototype accessor, or // instance for an object literal accessor). // `key` is the string or symbol property name for the accessor. // `descriptor` is the property descriptor for the accessor. } } ``` Ron From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Andrea Giammarchi Sent: Thursday, October 22, 2015 10:47 AM To: Yongxu Ren <renyongxu at gmail.com> Cc: es-discuss mailing list <es-discuss at mozilla.org> Subject: Re: Decorators for functions Removing ambiguity is my point since the very first post: current proposal is about a target, a property name, and a descriptor for such property ... having functions/variables decorators have no target (in strict mode undefined can't be a target, right?) and not necessarily a descriptor, or if any, always a data one with fields that makes no sense (like enumerable within a private scope ... what does that even mean) I'm all in for a distinct, separate, syntax to decorate "callables" or other variables as long as the current proposal will make for ES7 and won't be bothered by this different requirement. Regards On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com<mailto:renyongxu at gmail.com>> wrote: I don't think > ```@@ or @() or @::meomize``` would really help much, you can tell what the decorator does by simply looking at its name. And looks like you can not use @ and @@ for the same decorator function without adding extra condition checking inside the function. There are two patterns that we have discussed here, they are actually quite distinct. I still think we should support decorator on variables, but maybe we should have 2 distinct syntax for the normal decorators and "ambient decorators"(from Jonathan's post): 1. decorator that alter the code behavior, the currently proposed decorator. Such as ```@memoize``` 2. decorator that absolutely does not alter the code behavior, only used for optimization, checking or debugging. Instead of @, a distinct syntax will be much clearer ex.```@annotatition@``` (Maybe it should be called annotation instead?): ``` @deprecated@ @number,number=>string@/*type checking*/ @debug("this message will only print in development mode")@ ``` it sounds like terrible idea to have a decorator in code that you can not figure out if it will alter the code behavior by looking at it. I do like to see all the new ideas been added into javascript, but it is also necessary to eliminate the ambiguity whenever possible. On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron <jbondc at gdesolutions.com<mailto:jbondc at gdesolutions.com>> wrote: On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: > > determined at creation time, allowing for massive engine optimization, > Ya I'm not sure from which hat "massive engine optimization" comes from? What's meant is likely using decorators as annotations (compile time optimizations hints): http://www.google.com/patents/US7013458<https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> Or 'ambient decorators': https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators<https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> There's 2 patterns (maybe more?): (a) Tagging a 'tree transformation' on a node. (b) Metadata at compile time on a node. The thing about (b) is it can easily live outside of the code (like in typescript where you have an optional header/declaration file) With (a), it seems more conservative to see how it gets used with classes before bolting on to functions (opinion: end result in java is not something to be proud of). _______________________________________________ es-discuss mailing list es-discuss at mozilla.org<mailto: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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%3d> _______________________________________________ es-discuss mailing list es-discuss at mozilla.org<mailto: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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%3d> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151022/48815037/attachment-0001.html>
Ron, there's no way you can distinguish a class from a generic function in current specifications.
Having one argument won't tell me much, having a way to know that is not a class I need to decorate (traits/mixins) but just a function, so ignoring its prototype and do something else, would be cool but it's unfortunately not possible or portable.
How would you distinguish between a class or a function for a generic decorator? Or all you are saying is that decorators shouldn't be able to distinguish at all between a class, rather than a function?
Ron, there's **no way** you can distinguish a class from a generic function in current specifications. Having one argument won't tell me much, having a way to know that is not a class I need to decorate (traits/mixins) but just a function, so ignoring its prototype and do something else, would be cool but it's unfortunately not possible or portable. How would you distinguish between a class or a function for a generic decorator? Or all you are saying is that decorators shouldn't be able to distinguish at all between a class, rather than a function? Regards On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton <Ron.Buckton at microsoft.com> wrote: > Andrea, > > > > Is your concern about disambiguating the usage of a decorator at the call > site or within the body of the decorator? In the current proposal, you can > decorate a class member, or the class itself. > > > > When decorating a class member, three arguments are passed to the > decorator: The target, the property key (string or symbol), and the > descriptor. When decorating the class, one argument is passed to the > decorator: The constructor function. Generally this means that you can > disambiguate the usage of the decorator based simply on `arguments.length`, > or testing for `undefined` for the property key or descriptor. > > > > Would it be better to have a more consistent way to disambiguate the usage > of a decorator from within the decorator? This could be addressed with > something like a Reflect.getDecoratorUsage API or a `function.decoration` > meta-property or the like. Consider something like: > > > > ```js > > function memoize(target, key, descriptor) { > > switch (Reflect.getDecoratorUsage(arguments)) { > > case "class": > > // `target` is the class constructor. `key` and `descriptor` are > undefined. > > > > case "function": > > // `target` is the function. `key` and `descriptor` are undefined. > > > > case "method": > > // `target` is the object containing the method (e.g. constructor > > // for a static method, prototype for a prototype method, or > > // instance for an object literal method). > > // `key` is the string or symbol property name for the method. > > // `descriptor` is the property descriptor for the method. > > > > case "accessor": > > // `target` is the object containing the accessor (e.g. constructor > > // for a static accessor, prototype for a prototype accessor, or > > // instance for an object literal accessor). > > // `key` is the string or symbol property name for the accessor. > > // `descriptor` is the property descriptor for the accessor. > > } > > } > > ``` > > > > Ron > > > > *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On Behalf Of *Andrea > Giammarchi > *Sent:* Thursday, October 22, 2015 10:47 AM > *To:* Yongxu Ren <renyongxu at gmail.com> > *Cc:* es-discuss mailing list <es-discuss at mozilla.org> > *Subject:* Re: Decorators for functions > > > > Removing ambiguity is my point since the very first post: current proposal > is about a target, a property name, and a descriptor for such property ... > having functions/variables decorators have no target (in strict mode > undefined can't be a target, right?) and not necessarily a descriptor, or > if any, always a data one with fields that makes no sense (like enumerable > within a private scope ... what does that even mean) > > > > I'm all in for a distinct, separate, syntax to decorate "callables" or > other variables as long as the current proposal will make for ES7 and won't > be bothered by this different requirement. > > > > Regards > > > > > > > > On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> wrote: > > I don't think > > > > > ```@@ or @() or @::meomize``` > > > > would really help much, you can tell what the decorator does by simply > looking at its name. And looks like you can not use @ and @@ for the > same decorator function without adding extra condition checking inside the > function. > > > > There are two patterns that we have discussed here, they are actually > quite distinct. I still think we should support decorator on variables, but > maybe we should have 2 distinct syntax for the normal decorators and > "ambient decorators"(from Jonathan's post): > > > > 1. decorator that alter the code behavior, the currently proposed > decorator. Such as ```@memoize``` > > > > 2. decorator that absolutely does not alter the code behavior, only used > for optimization, checking or debugging. Instead of @, a distinct syntax > will be much clearer ex.```@annotatition@``` (Maybe it should be called > annotation instead?): > > ``` > > @deprecated@ > > > > @number,number=>string@/*type checking*/ > > > > @debug("this message will only print in development mode")@ > > ``` > > > > it sounds like terrible idea to have a decorator in code that you can not > figure out if it will alter the code behavior by looking at it. I do like > to see all the new ideas been added into javascript, but it is also > necessary to eliminate the ambiguity whenever possible. > > > > > > On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < > jbondc at gdesolutions.com> wrote: > > On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: > > > determined at creation time, allowing for massive engine optimization, > > > > Ya I'm not sure from which hat "massive engine optimization" comes from? > > What's meant is likely using decorators as annotations (compile time > optimizations hints): > http://www.google.com/patents/US7013458 > <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> > > Or 'ambient decorators': > > https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators > <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> > > There's 2 patterns (maybe more?): > (a) Tagging a 'tree transformation' on a node. > (b) Metadata at compile time on a node. > > The thing about (b) is it can easily live outside of the code (like in > typescript where you have an optional header/declaration file) > > With (a), it seems more conservative to see how it gets used with classes > before bolting on to functions (opinion: end result in java is not > something to be proud of). > > > _______________________________________________ > 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%3d> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151022/6a946f50/attachment-0001.html>
After reading the conversation, I think there is no ambiguity at all or, may be, it must be there: decorating a function should be like decorating a class, you can not distinguish between them and that's all. Just look at the code generated in Babel: babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator class A {}
You'll see:
A = decorator(A) || A;
And this is the traditional notion of decorator we see in Python and other languages. A simple way to check for a generic decorator would be:
function decorator(target, name='', descriptor=null) {
if (descriptor) console.log('Decorating a member');
else console.log('Decorating either a function or class');
}
And it's very consistent if you think the only difference a ES6 class introduces is that you are not allowed to call the class as a function.
So, the generated code for:
@decorator
function A() { }
Should be:
function A() {}
A = decorator(A) || A;
And that's all, if you always add the overwrite after the definition, hoisting is irrelevant but if it worries you, simply avoid hoisting when decorating as Axel suggested.
PS: Well thought, it must be possible for an hypothetical reflection function to determine if a function is a class or not as classes are marked to throw when they are not invoked with new.
Hi people. After reading the conversation, I think there is no ambiguity at all or, may be, it must be there: decorating a function should be like decorating a class, you can not distinguish between them and that's all. Just look at the code generated in Babel: https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} You'll see: ``` A = decorator(A) || A; ``` And this is the traditional notion of decorator we see in Python and other languages. A simple way to check for a generic decorator would be: ``` function decorator(target, name='', descriptor=null) { if (descriptor) console.log('Decorating a member'); else console.log('Decorating either a function or class'); } ``` And it's very consistent if you think the only difference a ES6 class introduces is that you are not allowed to call the class as a function. So, the generated code for: ``` @decorator function A() { } ``` Should be: ``` function A() {} A = decorator(A) || A; ``` And that's all, if you always add the overwrite after the definition, hoisting is irrelevant but if it worries you, simply avoid hoisting when decorating as Axel suggested. PS: Well thought, it must be possible for an hypothetical reflection function to determine if a function is a class or not as classes are marked to throw when they are not invoked with new. On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: > Ron, there's **no way** you can distinguish a class from a generic > function in current specifications. > > Having one argument won't tell me much, having a way to know that is not a > class I need to decorate (traits/mixins) but just a function, so ignoring > its prototype and do something else, would be cool but it's unfortunately > not possible or portable. > > How would you distinguish between a class or a function for a generic > decorator? Or all you are saying is that decorators shouldn't be able to > distinguish at all between a class, rather than a function? > > Regards > > > > > On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton <Ron.Buckton at microsoft.com> > wrote: > >> Andrea, >> >> >> >> Is your concern about disambiguating the usage of a decorator at the call >> site or within the body of the decorator? In the current proposal, you can >> decorate a class member, or the class itself. >> >> >> >> When decorating a class member, three arguments are passed to the >> decorator: The target, the property key (string or symbol), and the >> descriptor. When decorating the class, one argument is passed to the >> decorator: The constructor function. Generally this means that you can >> disambiguate the usage of the decorator based simply on `arguments.length`, >> or testing for `undefined` for the property key or descriptor. >> >> >> >> Would it be better to have a more consistent way to disambiguate the >> usage of a decorator from within the decorator? This could be addressed >> with something like a Reflect.getDecoratorUsage API or a >> `function.decoration` meta-property or the like. Consider something like: >> >> >> >> ```js >> >> function memoize(target, key, descriptor) { >> >> switch (Reflect.getDecoratorUsage(arguments)) { >> >> case "class": >> >> // `target` is the class constructor. `key` and `descriptor` are >> undefined. >> >> >> >> case "function": >> >> // `target` is the function. `key` and `descriptor` are undefined. >> >> >> >> case "method": >> >> // `target` is the object containing the method (e.g. constructor >> >> // for a static method, prototype for a prototype method, or >> >> // instance for an object literal method). >> >> // `key` is the string or symbol property name for the method. >> >> // `descriptor` is the property descriptor for the method. >> >> >> >> case "accessor": >> >> // `target` is the object containing the accessor (e.g. constructor >> >> // for a static accessor, prototype for a prototype accessor, or >> >> // instance for an object literal accessor). >> >> // `key` is the string or symbol property name for the accessor. >> >> // `descriptor` is the property descriptor for the accessor. >> >> } >> >> } >> >> ``` >> >> >> >> Ron >> >> >> >> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On Behalf Of >> *Andrea Giammarchi >> *Sent:* Thursday, October 22, 2015 10:47 AM >> *To:* Yongxu Ren <renyongxu at gmail.com> >> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >> *Subject:* Re: Decorators for functions >> >> >> >> Removing ambiguity is my point since the very first post: current >> proposal is about a target, a property name, and a descriptor for such >> property ... having functions/variables decorators have no target (in >> strict mode undefined can't be a target, right?) and not necessarily a >> descriptor, or if any, always a data one with fields that makes no sense >> (like enumerable within a private scope ... what does that even mean) >> >> >> >> I'm all in for a distinct, separate, syntax to decorate "callables" or >> other variables as long as the current proposal will make for ES7 and won't >> be bothered by this different requirement. >> >> >> >> Regards >> >> >> >> >> >> >> >> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> wrote: >> >> I don't think >> >> >> >> > ```@@ or @() or @::meomize``` >> >> >> >> would really help much, you can tell what the decorator does by simply >> looking at its name. And looks like you can not use @ and @@ for the >> same decorator function without adding extra condition checking inside the >> function. >> >> >> >> There are two patterns that we have discussed here, they are actually >> quite distinct. I still think we should support decorator on variables, but >> maybe we should have 2 distinct syntax for the normal decorators and >> "ambient decorators"(from Jonathan's post): >> >> >> >> 1. decorator that alter the code behavior, the currently proposed >> decorator. Such as ```@memoize``` >> >> >> >> 2. decorator that absolutely does not alter the code behavior, only used >> for optimization, checking or debugging. Instead of @, a distinct syntax >> will be much clearer ex.```@annotatition@``` (Maybe it should be called >> annotation instead?): >> >> ``` >> >> @deprecated@ >> >> >> >> @number,number=>string@/*type checking*/ >> >> >> >> @debug("this message will only print in development mode")@ >> >> ``` >> >> >> >> it sounds like terrible idea to have a decorator in code that you can not >> figure out if it will alter the code behavior by looking at it. I do like >> to see all the new ideas been added into javascript, but it is also >> necessary to eliminate the ambiguity whenever possible. >> >> >> >> >> >> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >> jbondc at gdesolutions.com> wrote: >> >> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >> > > determined at creation time, allowing for massive engine optimization, >> > >> >> Ya I'm not sure from which hat "massive engine optimization" comes from? >> >> What's meant is likely using decorators as annotations (compile time >> optimizations hints): >> http://www.google.com/patents/US7013458 >> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >> >> Or 'ambient decorators': >> >> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >> >> There's 2 patterns (maybe more?): >> (a) Tagging a 'tree transformation' on a node. >> (b) Metadata at compile time on a node. >> >> The thing about (b) is it can easily live outside of the code (like in >> typescript where you have an optional header/declaration file) >> >> With (a), it seems more conservative to see how it gets used with classes >> before bolting on to functions (opinion: end result in java is not >> something to be proud of). >> >> >> _______________________________________________ >> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151022/c2e68e66/attachment-0001.html>
which one is true?
I think there is no ambiguity at all ... decorating a function should be
like decorating a class
'cause I think those are very different things. You gonna wrap for sure the first one, you most likely ever even bother replacing the class, rather enriching its prototype or its public statics.
Maybe it's me overlooking at this, but the fact we cannot distinguish between classes and functions doesn't feel right to me.
P.S. babel has some target (browsers mostly, and nodejs) but it shouldn't be the reason to choose a pattern instead of another, or at least not the only one
which one is true? > I think there is no ambiguity at all ... decorating a function should be like decorating a class 'cause I think those are very different things. You gonna wrap for sure the first one, you most likely ever even bother replacing the class, rather enriching its prototype or its public statics. Maybe it's me overlooking at this, but the fact we cannot distinguish between classes and functions doesn't feel right to me. Regards P.S. babel has some target (browsers mostly, and nodejs) but it shouldn't be the reason to choose a pattern instead of another, or at least not the only one On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < salva at unoyunodiez.com> wrote: > Hi people. > > After reading the conversation, I think there is no ambiguity at all or, > may be, it must be there: decorating a function should be like decorating a > class, you can not distinguish between them and that's all. Just look at > the code generated in Babel: > > https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} > <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> > > You'll see: > > ``` > A = decorator(A) || A; > ``` > > And this is the traditional notion of decorator we see in Python and other > languages. A simple way to check for a generic decorator would be: > > ``` > function decorator(target, name='', descriptor=null) { > if (descriptor) console.log('Decorating a member'); > else console.log('Decorating either a function or class'); > } > ``` > > And it's very consistent if you think the only difference a ES6 class > introduces is that you are not allowed to call the class as a function. > > So, the generated code for: > > ``` > @decorator > function A() { } > ``` > > Should be: > > ``` > function A() {} > A = decorator(A) || A; > ``` > > And that's all, if you always add the overwrite after the definition, > hoisting is irrelevant but if it worries you, simply avoid hoisting when > decorating as Axel suggested. > > > PS: Well thought, it must be possible for an hypothetical reflection > function to determine if a function is a class or not as classes are marked > to throw when they are not invoked with new. > > On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> Ron, there's **no way** you can distinguish a class from a generic >> function in current specifications. >> >> Having one argument won't tell me much, having a way to know that is not >> a class I need to decorate (traits/mixins) but just a function, so ignoring >> its prototype and do something else, would be cool but it's unfortunately >> not possible or portable. >> >> How would you distinguish between a class or a function for a generic >> decorator? Or all you are saying is that decorators shouldn't be able to >> distinguish at all between a class, rather than a function? >> >> Regards >> >> >> >> >> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton <Ron.Buckton at microsoft.com> >> wrote: >> >>> Andrea, >>> >>> >>> >>> Is your concern about disambiguating the usage of a decorator at the >>> call site or within the body of the decorator? In the current proposal, you >>> can decorate a class member, or the class itself. >>> >>> >>> >>> When decorating a class member, three arguments are passed to the >>> decorator: The target, the property key (string or symbol), and the >>> descriptor. When decorating the class, one argument is passed to the >>> decorator: The constructor function. Generally this means that you can >>> disambiguate the usage of the decorator based simply on `arguments.length`, >>> or testing for `undefined` for the property key or descriptor. >>> >>> >>> >>> Would it be better to have a more consistent way to disambiguate the >>> usage of a decorator from within the decorator? This could be addressed >>> with something like a Reflect.getDecoratorUsage API or a >>> `function.decoration` meta-property or the like. Consider something like: >>> >>> >>> >>> ```js >>> >>> function memoize(target, key, descriptor) { >>> >>> switch (Reflect.getDecoratorUsage(arguments)) { >>> >>> case "class": >>> >>> // `target` is the class constructor. `key` and `descriptor` are >>> undefined. >>> >>> >>> >>> case "function": >>> >>> // `target` is the function. `key` and `descriptor` are undefined. >>> >>> >>> >>> case "method": >>> >>> // `target` is the object containing the method (e.g. constructor >>> >>> // for a static method, prototype for a prototype method, or >>> >>> // instance for an object literal method). >>> >>> // `key` is the string or symbol property name for the method. >>> >>> // `descriptor` is the property descriptor for the method. >>> >>> >>> >>> case "accessor": >>> >>> // `target` is the object containing the accessor (e.g. >>> constructor >>> >>> // for a static accessor, prototype for a prototype accessor, or >>> >>> // instance for an object literal accessor). >>> >>> // `key` is the string or symbol property name for the accessor. >>> >>> // `descriptor` is the property descriptor for the accessor. >>> >>> } >>> >>> } >>> >>> ``` >>> >>> >>> >>> Ron >>> >>> >>> >>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On Behalf >>> Of *Andrea Giammarchi >>> *Sent:* Thursday, October 22, 2015 10:47 AM >>> *To:* Yongxu Ren <renyongxu at gmail.com> >>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>> *Subject:* Re: Decorators for functions >>> >>> >>> >>> Removing ambiguity is my point since the very first post: current >>> proposal is about a target, a property name, and a descriptor for such >>> property ... having functions/variables decorators have no target (in >>> strict mode undefined can't be a target, right?) and not necessarily a >>> descriptor, or if any, always a data one with fields that makes no sense >>> (like enumerable within a private scope ... what does that even mean) >>> >>> >>> >>> I'm all in for a distinct, separate, syntax to decorate "callables" or >>> other variables as long as the current proposal will make for ES7 and won't >>> be bothered by this different requirement. >>> >>> >>> >>> Regards >>> >>> >>> >>> >>> >>> >>> >>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> wrote: >>> >>> I don't think >>> >>> >>> >>> > ```@@ or @() or @::meomize``` >>> >>> >>> >>> would really help much, you can tell what the decorator does by simply >>> looking at its name. And looks like you can not use @ and @@ for the >>> same decorator function without adding extra condition checking inside the >>> function. >>> >>> >>> >>> There are two patterns that we have discussed here, they are actually >>> quite distinct. I still think we should support decorator on variables, but >>> maybe we should have 2 distinct syntax for the normal decorators and >>> "ambient decorators"(from Jonathan's post): >>> >>> >>> >>> 1. decorator that alter the code behavior, the currently proposed >>> decorator. Such as ```@memoize``` >>> >>> >>> >>> 2. decorator that absolutely does not alter the code behavior, only used >>> for optimization, checking or debugging. Instead of @, a distinct syntax >>> will be much clearer ex.```@annotatition@``` (Maybe it should be called >>> annotation instead?): >>> >>> ``` >>> >>> @deprecated@ >>> >>> >>> >>> @number,number=>string@/*type checking*/ >>> >>> >>> >>> @debug("this message will only print in development mode")@ >>> >>> ``` >>> >>> >>> >>> it sounds like terrible idea to have a decorator in code that you can >>> not figure out if it will alter the code behavior by looking at it. I do >>> like to see all the new ideas been added into javascript, but it is also >>> necessary to eliminate the ambiguity whenever possible. >>> >>> >>> >>> >>> >>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>> jbondc at gdesolutions.com> wrote: >>> >>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>> > > determined at creation time, allowing for massive engine >>> optimization, >>> > >>> >>> Ya I'm not sure from which hat "massive engine optimization" comes from? >>> >>> What's meant is likely using decorators as annotations (compile time >>> optimizations hints): >>> http://www.google.com/patents/US7013458 >>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>> >>> Or 'ambient decorators': >>> >>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>> >>> There's 2 patterns (maybe more?): >>> (a) Tagging a 'tree transformation' on a node. >>> (b) Metadata at compile time on a node. >>> >>> The thing about (b) is it can easily live outside of the code (like in >>> typescript where you have an optional header/declaration file) >>> >>> With (a), it seems more conservative to see how it gets used with >>> classes before bolting on to functions (opinion: end result in java is not >>> something to be proud of). >>> >>> >>> _______________________________________________ >>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151022/8e948562/attachment-0001.html>
-----Original Message----- From: Andrea Giammarchi [mailto:andrea.giammarchi at gmail.com] Sent: Thursday, October 22, 2015 12:53 PM
Ron, there's no way you can distinguish a class from a generic function in current specifications.
Yes, this is true. However, decorators aren't in the current specification either. If this becomes a must-have then we should investigate an API or meta-property that could expose this information, as I mentioned in my previous reply.
Having one argument won't tell me much, having a way to know that is not a class I need to decorate (traits/mixins) but just a function, so ignoring its prototype and do something else, would be cool but it's unfortunately not possible or portable.
How would you distinguish between a class or a function for a generic decorator? Or all you are saying is that decorators shouldn't be able to distinguish at all between a class, rather than a function?
While I think it would be a valuable feature to be able to distinguish between a class and a function, it may make it difficult to properly reason between an ES6 class and an ES5/3 function-as-a-class-constructor. The possibility of adding a "call constructor" further complicates this.
It's useful to be able to disambiguate within the decorator, so I can know whether I would need to maintain a prototype chain:
function someDecorator(target) {
// using "function.decoration" as a possible meta-property
if (function.decoration === "class") {
return class extends target {
constructor(...args) {
// do something in constructor...
super(...args);
}
};
}
else if (function.decoration === "function") {
return function(...args) {
// do something in function...
return target(...args);
};
}
}
Alternatively, it would be interesting if all class declarations were implicitly given a Symbol.class property on the constructor declaration. This way older function-as-a-class-constructor implementations could opt-in to stating "I'm a class":
function someDecorator(target) {
if (arguments.length !== 1) throw new TypeError(); // only for class/function
if (target.hasOwnProperty(Symbol.class)) {
// class
}
else {
// function
}
}
// up-level
@someDecorator
class ES6Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
// down-level
function Point(x, y) {
this.x = x;
this.y = y;
}
Point[Symbol.class] = true;
Point = someDecorator(Point) || Point;
Ron
> -----Original Message----- > From: Andrea Giammarchi [mailto:andrea.giammarchi at gmail.com] > Sent: Thursday, October 22, 2015 12:53 PM > Ron, there's **no way** you can distinguish a class from a generic function > in current specifications. Yes, this is true. However, decorators aren't in the current specification either. If this becomes a must-have then we should investigate an API or meta-property that could expose this information, as I mentioned in my previous reply. > Having one argument won't tell me much, having a way to know that is not a > class I need to decorate (traits/mixins) but just a function, so ignoring its > prototype and do something else, would be cool but it's unfortunately not > possible or portable. > > How would you distinguish between a class or a function for a generic > decorator? Or all you are saying is that decorators shouldn't be able to > distinguish at all between a class, rather than a function? While I think it would be a valuable feature to be able to distinguish between a class and a function, it may make it difficult to properly reason between an ES6 class and an ES5/3 function-as-a-class-constructor. The possibility of adding a "call constructor" further complicates this. It's useful to be able to disambiguate within the decorator, so I can know whether I would need to maintain a prototype chain: ```js function someDecorator(target) { // using "function.decoration" as a possible meta-property if (function.decoration === "class") { return class extends target { constructor(...args) { // do something in constructor... super(...args); } }; } else if (function.decoration === "function") { return function(...args) { // do something in function... return target(...args); }; } } ``` Alternatively, it would be interesting if all class declarations were implicitly given a Symbol.class property on the constructor declaration. This way older function-as-a-class-constructor implementations could opt-in to stating "I'm a class": ```js function someDecorator(target) { if (arguments.length !== 1) throw new TypeError(); // only for class/function if (target.hasOwnProperty(Symbol.class)) { // class } else { // function } } // up-level @someDecorator class ES6Point { constructor(x, y) { this.x = x; this.y = y; } } // down-level function Point(x, y) { this.x = x; this.y = y; } Point[Symbol.class] = true; Point = someDecorator(Point) || Point; ``` Ron
It's all OK to discuss this for the future, meanwhile there won't be a way to tell older engines the difference, which is the portability concern I've been talking about.
I guess thought it would be very misleading to have decorators that accepts both classes and regular functions, so maybe the problem, while it exists from reflection point of view, won't bother real-world code and I'm just overlooking at this.
Best
It's all OK to discuss this for the future, meanwhile there won't be a way to tell older engines the difference, which is the portability concern I've been talking about. I guess thought it would be very misleading to have decorators that accepts both classes and regular functions, so maybe the problem, while it exists from reflection point of view, won't bother real-world code and I'm just overlooking at this. Best Regards On Thu, Oct 22, 2015 at 9:41 PM, Ron Buckton <Ron.Buckton at microsoft.com> wrote: > > -----Original Message----- > > From: Andrea Giammarchi [mailto:andrea.giammarchi at gmail.com] > > Sent: Thursday, October 22, 2015 12:53 PM > > > Ron, there's **no way** you can distinguish a class from a generic > function > > in current specifications. > > Yes, this is true. However, decorators aren't in the current specification > either. If this becomes a must-have then we should investigate an API or > meta-property that could expose this information, as I mentioned in my > previous reply. > > > Having one argument won't tell me much, having a way to know that is not > a > > class I need to decorate (traits/mixins) but just a function, so > ignoring its > > prototype and do something else, would be cool but it's unfortunately not > > possible or portable. > > > > How would you distinguish between a class or a function for a generic > > decorator? Or all you are saying is that decorators shouldn't be able to > > distinguish at all between a class, rather than a function? > > While I think it would be a valuable feature to be able to distinguish > between a class and a function, it may make it difficult to properly reason > between an ES6 class and an ES5/3 function-as-a-class-constructor. The > possibility of adding a "call constructor" further complicates this. > > It's useful to be able to disambiguate within the decorator, so I can know > whether I would need to maintain a prototype chain: > > ```js > function someDecorator(target) { > // using "function.decoration" as a possible meta-property > if (function.decoration === "class") { > return class extends target { > constructor(...args) { > // do something in constructor... > super(...args); > } > }; > } > else if (function.decoration === "function") { > return function(...args) { > // do something in function... > return target(...args); > }; > } > } > ``` > > Alternatively, it would be interesting if all class declarations were > implicitly given a Symbol.class property on the constructor declaration. > This way older function-as-a-class-constructor implementations could opt-in > to stating "I'm a class": > > ```js > function someDecorator(target) { > if (arguments.length !== 1) throw new TypeError(); // only for > class/function > if (target.hasOwnProperty(Symbol.class)) { > // class > } > else { > // function > } > } > > // up-level > @someDecorator > class ES6Point { > constructor(x, y) { > this.x = x; > this.y = y; > } > } > > // down-level > function Point(x, y) { > this.x = x; > this.y = y; > } > Point[Symbol.class] = true; > Point = someDecorator(Point) || Point; > ``` > > Ron > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151022/e329a4da/attachment-0001.html>
Andrea,
My point wasn’t to implement something that allows the decorator function to figure out the difference between class and function. The point is to be able to show the difference in your code, so that it can tell the developer what the code is doing.
Also, the [‘ambient decorator’ ](jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators, jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators) Jonathan mentioned is what I think why we should have a new syntax for(decorator that absolutely does not alter the code behavior, only used for optimization, checking or debugging should have different syntax from decorator that alter the code behavior).
Andrea, My point wasn’t to implement something that allows the decorator function to figure out the difference between class and function. The point is to be able to show the difference in your code, so that it can tell the developer what the code is doing. Also, the [‘ambient decorator’ ](https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators <https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators>) Jonathan mentioned is what I think why we should have a new syntax for(decorator that absolutely does not alter the code behavior, only used for optimization, checking or debugging should have different syntax from decorator that alter the code behavior). -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151022/163ff545/attachment.html>
I think I am quite off topic, how about this solution:
If we restrict only use decorator on class
And use @annotation@
decorator that absolutely does not alter the code behavior for functions, for the ambient case?
I think I am quite off topic, how about this solution: If we restrict only use decorator on class And use ```@annotation@``` decorator that absolutely does not alter the code behavior for functions, for the ambient case? -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151022/c6697e94/attachment.html>
On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:
which one is true?
I think there is no ambiguity at all ... decorating a function should be like decorating a class
'cause I think those are very different things.
As far as I know, classes in ES6, apart from preventing you from calling
without new
(and minor subclassing details), are identical to functions.
You gonna wrap for sure the first one, you most likely ever even bother replacing the class, rather enriching its prototype or its public statics.
Well, is not as sure you want to wrap a function at all. Suppose:
// operaations.js
@priority(2)
function taskA() { doSomething(); }
@priority(1)
function taskB() { doSomething(); }
@priority(5)
function taskC() { doSomething(); }
taskManager.register(taskA, taskB, taskC);
taskManager.run(); // run taking into account priority symbol of the
functions
// taskManager.js
var priority = new Symbol();
function priority(p) {
return function(target) { target[priority] = p; }
}
On the contrary, you would want to replace a class completely:
@singleton
class system {
get version() { return '1.0.0'; }
get drives() { return ...; }
}
console.log(system.version);
function singleton(target) {
return target();
}
I'm not saying is not important to distinguish between classes and
functions, I'm just saying, it is not as important and not critical for the
decorator syntax. It suffices for a framework to make their classes to
inherit from a custom base object with a symbol isClass
set to true to
allow their own decorators to distinguish between classes and functions but
these are specific-implementation details. What is true is the the syntax
works for regular functions and class based functions.
Maybe it's me overlooking at this, but the fact we cannot distinguish between classes and functions doesn't feel right to me.
No, sorry, maybe it's me that I can not see a harmful side effect here. Can you point me some example where not distinguishing between functions and classes would be fatal, please? Maybe this way, I (and others) understand your concerns.
P.S. babel has some target (browsers mostly, and nodejs) but it shouldn't be the reason to choose a pattern instead of another, or at least not the only one
Of course, but it is a clear indicator of semantics. It's very valuable for a language to allow its own declarative semantics to be expressed in a programmatic fashion as it denotes a very consistent and versatile data & execution models.
Hi Andrea. On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: > which one is true? > > > I think there is no ambiguity at all ... decorating a function should > be like decorating a class > > 'cause I think those are very different things. > As far as I know, classes in ES6, apart from preventing you from calling without `new` (and minor subclassing details), are identical to functions. > You gonna wrap for sure the first one, you most likely ever even bother > replacing the class, rather enriching its prototype or its public statics. > Well, is not as sure you want to wrap a function at all. Suppose: ``` // operaations.js @priority(2) function taskA() { doSomething(); } @priority(1) function taskB() { doSomething(); } @priority(5) function taskC() { doSomething(); } taskManager.register(taskA, taskB, taskC); taskManager.run(); // run taking into account priority symbol of the functions // taskManager.js var priority = new Symbol(); function priority(p) { return function(target) { target[priority] = p; } } ``` On the contrary, you would want to replace a class completely: ``` @singleton class system { get version() { return '1.0.0'; } get drives() { return ...; } } console.log(system.version); function singleton(target) { return target(); } ``` I'm not saying is not important to distinguish between classes and functions, I'm just saying, it is not as important and not critical for the decorator syntax. It suffices for a framework to make their classes to inherit from a custom base object with a symbol `isClass` set to true to allow their own decorators to distinguish between classes and functions but these are specific-implementation details. What is true is the the syntax works for regular functions and class based functions. > > Maybe it's me overlooking at this, but the fact we cannot distinguish > between classes and functions doesn't feel right to me. > No, sorry, maybe it's me that I can not see a harmful side effect here. Can you point me some example where not distinguishing between functions and classes would be fatal, please? Maybe this way, I (and others) understand your concerns. > > Regards > > P.S. babel has some target (browsers mostly, and nodejs) but it shouldn't > be the reason to choose a pattern instead of another, or at least not the > only one > Of course, but it is a clear indicator of semantics. It's very valuable for a language to allow its own declarative semantics to be expressed in a programmatic fashion as it denotes a very consistent and versatile data & execution models. > > > > > > On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < > salva at unoyunodiez.com> wrote: > >> Hi people. >> >> After reading the conversation, I think there is no ambiguity at all or, >> may be, it must be there: decorating a function should be like decorating a >> class, you can not distinguish between them and that's all. Just look at >> the code generated in Babel: >> >> https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} >> <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> >> >> You'll see: >> >> ``` >> A = decorator(A) || A; >> ``` >> >> And this is the traditional notion of decorator we see in Python and >> other languages. A simple way to check for a generic decorator would be: >> >> ``` >> function decorator(target, name='', descriptor=null) { >> if (descriptor) console.log('Decorating a member'); >> else console.log('Decorating either a function or class'); >> } >> ``` >> >> And it's very consistent if you think the only difference a ES6 class >> introduces is that you are not allowed to call the class as a function. >> >> So, the generated code for: >> >> ``` >> @decorator >> function A() { } >> ``` >> >> Should be: >> >> ``` >> function A() {} >> A = decorator(A) || A; >> ``` >> >> And that's all, if you always add the overwrite after the definition, >> hoisting is irrelevant but if it worries you, simply avoid hoisting when >> decorating as Axel suggested. >> >> >> PS: Well thought, it must be possible for an hypothetical reflection >> function to determine if a function is a class or not as classes are marked >> to throw when they are not invoked with new. >> >> On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> Ron, there's **no way** you can distinguish a class from a generic >>> function in current specifications. >>> >>> Having one argument won't tell me much, having a way to know that is not >>> a class I need to decorate (traits/mixins) but just a function, so ignoring >>> its prototype and do something else, would be cool but it's unfortunately >>> not possible or portable. >>> >>> How would you distinguish between a class or a function for a generic >>> decorator? Or all you are saying is that decorators shouldn't be able to >>> distinguish at all between a class, rather than a function? >>> >>> Regards >>> >>> >>> >>> >>> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton <Ron.Buckton at microsoft.com> >>> wrote: >>> >>>> Andrea, >>>> >>>> >>>> >>>> Is your concern about disambiguating the usage of a decorator at the >>>> call site or within the body of the decorator? In the current proposal, you >>>> can decorate a class member, or the class itself. >>>> >>>> >>>> >>>> When decorating a class member, three arguments are passed to the >>>> decorator: The target, the property key (string or symbol), and the >>>> descriptor. When decorating the class, one argument is passed to the >>>> decorator: The constructor function. Generally this means that you can >>>> disambiguate the usage of the decorator based simply on `arguments.length`, >>>> or testing for `undefined` for the property key or descriptor. >>>> >>>> >>>> >>>> Would it be better to have a more consistent way to disambiguate the >>>> usage of a decorator from within the decorator? This could be addressed >>>> with something like a Reflect.getDecoratorUsage API or a >>>> `function.decoration` meta-property or the like. Consider something like: >>>> >>>> >>>> >>>> ```js >>>> >>>> function memoize(target, key, descriptor) { >>>> >>>> switch (Reflect.getDecoratorUsage(arguments)) { >>>> >>>> case "class": >>>> >>>> // `target` is the class constructor. `key` and `descriptor` are >>>> undefined. >>>> >>>> >>>> >>>> case "function": >>>> >>>> // `target` is the function. `key` and `descriptor` are undefined. >>>> >>>> >>>> >>>> case "method": >>>> >>>> // `target` is the object containing the method (e.g. constructor >>>> >>>> // for a static method, prototype for a prototype method, or >>>> >>>> // instance for an object literal method). >>>> >>>> // `key` is the string or symbol property name for the method. >>>> >>>> // `descriptor` is the property descriptor for the method. >>>> >>>> >>>> >>>> case "accessor": >>>> >>>> // `target` is the object containing the accessor (e.g. >>>> constructor >>>> >>>> // for a static accessor, prototype for a prototype accessor, or >>>> >>>> // instance for an object literal accessor). >>>> >>>> // `key` is the string or symbol property name for the accessor. >>>> >>>> // `descriptor` is the property descriptor for the accessor. >>>> >>>> } >>>> >>>> } >>>> >>>> ``` >>>> >>>> >>>> >>>> Ron >>>> >>>> >>>> >>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On Behalf >>>> Of *Andrea Giammarchi >>>> *Sent:* Thursday, October 22, 2015 10:47 AM >>>> *To:* Yongxu Ren <renyongxu at gmail.com> >>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>>> *Subject:* Re: Decorators for functions >>>> >>>> >>>> >>>> Removing ambiguity is my point since the very first post: current >>>> proposal is about a target, a property name, and a descriptor for such >>>> property ... having functions/variables decorators have no target (in >>>> strict mode undefined can't be a target, right?) and not necessarily a >>>> descriptor, or if any, always a data one with fields that makes no sense >>>> (like enumerable within a private scope ... what does that even mean) >>>> >>>> >>>> >>>> I'm all in for a distinct, separate, syntax to decorate "callables" or >>>> other variables as long as the current proposal will make for ES7 and won't >>>> be bothered by this different requirement. >>>> >>>> >>>> >>>> Regards >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> >>>> wrote: >>>> >>>> I don't think >>>> >>>> >>>> >>>> > ```@@ or @() or @::meomize``` >>>> >>>> >>>> >>>> would really help much, you can tell what the decorator does by simply >>>> looking at its name. And looks like you can not use @ and @@ for the >>>> same decorator function without adding extra condition checking inside the >>>> function. >>>> >>>> >>>> >>>> There are two patterns that we have discussed here, they are actually >>>> quite distinct. I still think we should support decorator on variables, but >>>> maybe we should have 2 distinct syntax for the normal decorators and >>>> "ambient decorators"(from Jonathan's post): >>>> >>>> >>>> >>>> 1. decorator that alter the code behavior, the currently proposed >>>> decorator. Such as ```@memoize``` >>>> >>>> >>>> >>>> 2. decorator that absolutely does not alter the code behavior, only >>>> used for optimization, checking or debugging. Instead of @, a distinct >>>> syntax will be much clearer ex.```@annotatition@``` (Maybe it should >>>> be called annotation instead?): >>>> >>>> ``` >>>> >>>> @deprecated@ >>>> >>>> >>>> >>>> @number,number=>string@/*type checking*/ >>>> >>>> >>>> >>>> @debug("this message will only print in development mode")@ >>>> >>>> ``` >>>> >>>> >>>> >>>> it sounds like terrible idea to have a decorator in code that you can >>>> not figure out if it will alter the code behavior by looking at it. I do >>>> like to see all the new ideas been added into javascript, but it is also >>>> necessary to eliminate the ambiguity whenever possible. >>>> >>>> >>>> >>>> >>>> >>>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>>> jbondc at gdesolutions.com> wrote: >>>> >>>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>>> > > determined at creation time, allowing for massive engine >>>> optimization, >>>> > >>>> >>>> Ya I'm not sure from which hat "massive engine optimization" comes from? >>>> >>>> What's meant is likely using decorators as annotations (compile time >>>> optimizations hints): >>>> http://www.google.com/patents/US7013458 >>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>>> >>>> Or 'ambient decorators': >>>> >>>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>>> >>>> There's 2 patterns (maybe more?): >>>> (a) Tagging a 'tree transformation' on a node. >>>> (b) Metadata at compile time on a node. >>>> >>>> The thing about (b) is it can easily live outside of the code (like in >>>> typescript where you have an optional header/declaration file) >>>> >>>> With (a), it seems more conservative to see how it gets used with >>>> classes before bolting on to functions (opinion: end result in java is not >>>> something to be proud of). >>>> >>>> >>>> _______________________________________________ >>>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151023/9fa56b70/attachment-0001.html>
well
Can you point me some example where not distinguishing between functions
and classes would be fatal, please?
the fact a class throws once invoked like a function isn't enough fatal to you?
function invokeThat() {
var result = Object.create(this.prototype);
return this.apply(result, arguments) || result;
}
invokeThat.call(function sum(a, b) { return a + b; }, 1, 2); // 3
invokeThat.call(class Point{constructor(x,y){this.x=x;this.y=y;}}, 10, 15);
// Uncaught TypeError: Class constructors cannot be invoked without 'new'(…)
We are missing a Reflection.isClass
... useful or not, we've got two kind
of "invokables" and nobody can distinguish from them.
well > Can you point me some example where not distinguishing between functions and classes would be fatal, please? the fact a class throws once invoked like a function isn't enough fatal to you? ```js function invokeThat() { var result = Object.create(this.prototype); return this.apply(result, arguments) || result; } invokeThat.call(function sum(a, b) { return a + b; }, 1, 2); // 3 invokeThat.call(class Point{constructor(x,y){this.x=x;this.y=y;}}, 10, 15); // Uncaught TypeError: Class constructors cannot be invoked without 'new'(…) ``` We are missing a `Reflection.isClass` ... useful or not, we've got two kind of "invokables" and nobody can distinguish from them. Regards On Fri, Oct 23, 2015 at 10:56 AM, Salvador de la Puente González < salva at unoyunodiez.com> wrote: > Hi Andrea. > > On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> which one is true? >> >> > I think there is no ambiguity at all ... decorating a function should >> be like decorating a class >> >> 'cause I think those are very different things. >> > > As far as I know, classes in ES6, apart from preventing you from calling > without `new` (and minor subclassing details), are identical to functions. > > >> You gonna wrap for sure the first one, you most likely ever even bother >> replacing the class, rather enriching its prototype or its public statics. >> > > Well, is not as sure you want to wrap a function at all. Suppose: > > ``` > // operaations.js > @priority(2) > function taskA() { doSomething(); } > > @priority(1) > function taskB() { doSomething(); } > > @priority(5) > function taskC() { doSomething(); } > > taskManager.register(taskA, taskB, taskC); > taskManager.run(); // run taking into account priority symbol of the > functions > > // taskManager.js > var priority = new Symbol(); > > function priority(p) { > return function(target) { target[priority] = p; } > } > ``` > > On the contrary, you would want to replace a class completely: > > ``` > @singleton > class system { > get version() { return '1.0.0'; } > get drives() { return ...; } > } > > console.log(system.version); > > function singleton(target) { > return target(); > } > ``` > > I'm not saying is not important to distinguish between classes and > functions, I'm just saying, it is not as important and not critical for the > decorator syntax. It suffices for a framework to make their classes to > inherit from a custom base object with a symbol `isClass` set to true to > allow their own decorators to distinguish between classes and functions but > these are specific-implementation details. What is true is the the syntax > works for regular functions and class based functions. > > >> >> Maybe it's me overlooking at this, but the fact we cannot distinguish >> between classes and functions doesn't feel right to me. >> > > No, sorry, maybe it's me that I can not see a harmful side effect here. > Can you point me some example where not distinguishing between functions > and classes would be fatal, please? Maybe this way, I (and others) > understand your concerns. > > >> >> Regards >> >> P.S. babel has some target (browsers mostly, and nodejs) but it shouldn't >> be the reason to choose a pattern instead of another, or at least not the >> only one >> > > Of course, but it is a clear indicator of semantics. It's very valuable > for a language to allow its own declarative semantics to be expressed in a > programmatic fashion as it denotes a very consistent and versatile data & > execution models. > > >> >> >> >> >> >> On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < >> salva at unoyunodiez.com> wrote: >> >>> Hi people. >>> >>> After reading the conversation, I think there is no ambiguity at all or, >>> may be, it must be there: decorating a function should be like decorating a >>> class, you can not distinguish between them and that's all. Just look at >>> the code generated in Babel: >>> >>> https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} >>> <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> >>> >>> You'll see: >>> >>> ``` >>> A = decorator(A) || A; >>> ``` >>> >>> And this is the traditional notion of decorator we see in Python and >>> other languages. A simple way to check for a generic decorator would be: >>> >>> ``` >>> function decorator(target, name='', descriptor=null) { >>> if (descriptor) console.log('Decorating a member'); >>> else console.log('Decorating either a function or class'); >>> } >>> ``` >>> >>> And it's very consistent if you think the only difference a ES6 class >>> introduces is that you are not allowed to call the class as a function. >>> >>> So, the generated code for: >>> >>> ``` >>> @decorator >>> function A() { } >>> ``` >>> >>> Should be: >>> >>> ``` >>> function A() {} >>> A = decorator(A) || A; >>> ``` >>> >>> And that's all, if you always add the overwrite after the definition, >>> hoisting is irrelevant but if it worries you, simply avoid hoisting when >>> decorating as Axel suggested. >>> >>> >>> PS: Well thought, it must be possible for an hypothetical reflection >>> function to determine if a function is a class or not as classes are marked >>> to throw when they are not invoked with new. >>> >>> On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> Ron, there's **no way** you can distinguish a class from a generic >>>> function in current specifications. >>>> >>>> Having one argument won't tell me much, having a way to know that is >>>> not a class I need to decorate (traits/mixins) but just a function, so >>>> ignoring its prototype and do something else, would be cool but it's >>>> unfortunately not possible or portable. >>>> >>>> How would you distinguish between a class or a function for a generic >>>> decorator? Or all you are saying is that decorators shouldn't be able to >>>> distinguish at all between a class, rather than a function? >>>> >>>> Regards >>>> >>>> >>>> >>>> >>>> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton <Ron.Buckton at microsoft.com >>>> > wrote: >>>> >>>>> Andrea, >>>>> >>>>> >>>>> >>>>> Is your concern about disambiguating the usage of a decorator at the >>>>> call site or within the body of the decorator? In the current proposal, you >>>>> can decorate a class member, or the class itself. >>>>> >>>>> >>>>> >>>>> When decorating a class member, three arguments are passed to the >>>>> decorator: The target, the property key (string or symbol), and the >>>>> descriptor. When decorating the class, one argument is passed to the >>>>> decorator: The constructor function. Generally this means that you can >>>>> disambiguate the usage of the decorator based simply on `arguments.length`, >>>>> or testing for `undefined` for the property key or descriptor. >>>>> >>>>> >>>>> >>>>> Would it be better to have a more consistent way to disambiguate the >>>>> usage of a decorator from within the decorator? This could be addressed >>>>> with something like a Reflect.getDecoratorUsage API or a >>>>> `function.decoration` meta-property or the like. Consider something like: >>>>> >>>>> >>>>> >>>>> ```js >>>>> >>>>> function memoize(target, key, descriptor) { >>>>> >>>>> switch (Reflect.getDecoratorUsage(arguments)) { >>>>> >>>>> case "class": >>>>> >>>>> // `target` is the class constructor. `key` and `descriptor` are >>>>> undefined. >>>>> >>>>> >>>>> >>>>> case "function": >>>>> >>>>> // `target` is the function. `key` and `descriptor` are >>>>> undefined. >>>>> >>>>> >>>>> >>>>> case "method": >>>>> >>>>> // `target` is the object containing the method (e.g. >>>>> constructor >>>>> >>>>> // for a static method, prototype for a prototype method, or >>>>> >>>>> // instance for an object literal method). >>>>> >>>>> // `key` is the string or symbol property name for the method. >>>>> >>>>> // `descriptor` is the property descriptor for the method. >>>>> >>>>> >>>>> >>>>> case "accessor": >>>>> >>>>> // `target` is the object containing the accessor (e.g. >>>>> constructor >>>>> >>>>> // for a static accessor, prototype for a prototype accessor, or >>>>> >>>>> // instance for an object literal accessor). >>>>> >>>>> // `key` is the string or symbol property name for the accessor. >>>>> >>>>> // `descriptor` is the property descriptor for the accessor. >>>>> >>>>> } >>>>> >>>>> } >>>>> >>>>> ``` >>>>> >>>>> >>>>> >>>>> Ron >>>>> >>>>> >>>>> >>>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On Behalf >>>>> Of *Andrea Giammarchi >>>>> *Sent:* Thursday, October 22, 2015 10:47 AM >>>>> *To:* Yongxu Ren <renyongxu at gmail.com> >>>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>>>> *Subject:* Re: Decorators for functions >>>>> >>>>> >>>>> >>>>> Removing ambiguity is my point since the very first post: current >>>>> proposal is about a target, a property name, and a descriptor for such >>>>> property ... having functions/variables decorators have no target (in >>>>> strict mode undefined can't be a target, right?) and not necessarily a >>>>> descriptor, or if any, always a data one with fields that makes no sense >>>>> (like enumerable within a private scope ... what does that even mean) >>>>> >>>>> >>>>> >>>>> I'm all in for a distinct, separate, syntax to decorate "callables" or >>>>> other variables as long as the current proposal will make for ES7 and won't >>>>> be bothered by this different requirement. >>>>> >>>>> >>>>> >>>>> Regards >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> >>>>> wrote: >>>>> >>>>> I don't think >>>>> >>>>> >>>>> >>>>> > ```@@ or @() or @::meomize``` >>>>> >>>>> >>>>> >>>>> would really help much, you can tell what the decorator does by simply >>>>> looking at its name. And looks like you can not use @ and @@ for the >>>>> same decorator function without adding extra condition checking inside the >>>>> function. >>>>> >>>>> >>>>> >>>>> There are two patterns that we have discussed here, they are actually >>>>> quite distinct. I still think we should support decorator on variables, but >>>>> maybe we should have 2 distinct syntax for the normal decorators and >>>>> "ambient decorators"(from Jonathan's post): >>>>> >>>>> >>>>> >>>>> 1. decorator that alter the code behavior, the currently proposed >>>>> decorator. Such as ```@memoize``` >>>>> >>>>> >>>>> >>>>> 2. decorator that absolutely does not alter the code behavior, only >>>>> used for optimization, checking or debugging. Instead of @, a distinct >>>>> syntax will be much clearer ex.```@annotatition@``` (Maybe it should >>>>> be called annotation instead?): >>>>> >>>>> ``` >>>>> >>>>> @deprecated@ >>>>> >>>>> >>>>> >>>>> @number,number=>string@/*type checking*/ >>>>> >>>>> >>>>> >>>>> @debug("this message will only print in development mode")@ >>>>> >>>>> ``` >>>>> >>>>> >>>>> >>>>> it sounds like terrible idea to have a decorator in code that you can >>>>> not figure out if it will alter the code behavior by looking at it. I do >>>>> like to see all the new ideas been added into javascript, but it is also >>>>> necessary to eliminate the ambiguity whenever possible. >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>>>> jbondc at gdesolutions.com> wrote: >>>>> >>>>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>>>> > > determined at creation time, allowing for massive engine >>>>> optimization, >>>>> > >>>>> >>>>> Ya I'm not sure from which hat "massive engine optimization" comes >>>>> from? >>>>> >>>>> What's meant is likely using decorators as annotations (compile time >>>>> optimizations hints): >>>>> http://www.google.com/patents/US7013458 >>>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>>>> >>>>> Or 'ambient decorators': >>>>> >>>>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>>>> >>>>> There's 2 patterns (maybe more?): >>>>> (a) Tagging a 'tree transformation' on a node. >>>>> (b) Metadata at compile time on a node. >>>>> >>>>> The thing about (b) is it can easily live outside of the code (like in >>>>> typescript where you have an optional header/declaration file) >>>>> >>>>> With (a), it seems more conservative to see how it gets used with >>>>> classes before bolting on to functions (opinion: end result in java is not >>>>> something to be proud of). >>>>> >>>>> >>>>> _______________________________________________ >>>>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151023/33984247/attachment-0001.html>
Well, I see, it's not worse than other dynamic typing issues (think about
invokeThat.call()
being called on undefined or null, the exception only
gives you a runtime error and you could always wrap in a try-catch, see the
message and translate to yoour own exception or recover) but that does not
relate at all with decorators which is my point. I agree on
Reflection.isClass
although I should check the spec in the search for
something related with that specific topic but returning to the previous
discussion about which syntax to use when decorating functions, I don't see
this is a blocker for extending present decorator syntax to functions.
Well, I see, it's not worse than other dynamic typing issues (think about `invokeThat.call()` being called on undefined or null, the exception only gives you a runtime error and you could always wrap in a try-catch, see the message and translate to yoour own exception or recover) but that does not relate at all with decorators which is my point. I agree on `Reflection.isClass` although I should check the spec in the search for something related with that specific topic but returning to the previous discussion about which syntax to use when decorating functions, I don't see this is a blocker for extending present decorator syntax to functions. On Fri, Oct 23, 2015 at 12:17 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: > well > > > Can you point me some example where not distinguishing between > functions and classes would be fatal, please? > > the fact a class throws once invoked like a function isn't enough fatal to > you? > > ```js > function invokeThat() { > var result = Object.create(this.prototype); > return this.apply(result, arguments) || result; > } > > invokeThat.call(function sum(a, b) { return a + b; }, 1, 2); // 3 > > invokeThat.call(class Point{constructor(x,y){this.x=x;this.y=y;}}, 10, > 15); > // Uncaught TypeError: Class constructors cannot be invoked without > 'new'(…) > ``` > > We are missing a `Reflection.isClass` ... useful or not, we've got two > kind of "invokables" and nobody can distinguish from them. > > Regards > > > > > On Fri, Oct 23, 2015 at 10:56 AM, Salvador de la Puente González < > salva at unoyunodiez.com> wrote: > >> Hi Andrea. >> >> On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> which one is true? >>> >>> > I think there is no ambiguity at all ... decorating a function should >>> be like decorating a class >>> >>> 'cause I think those are very different things. >>> >> >> As far as I know, classes in ES6, apart from preventing you from calling >> without `new` (and minor subclassing details), are identical to functions. >> >> >>> You gonna wrap for sure the first one, you most likely ever even bother >>> replacing the class, rather enriching its prototype or its public statics. >>> >> >> Well, is not as sure you want to wrap a function at all. Suppose: >> >> ``` >> // operaations.js >> @priority(2) >> function taskA() { doSomething(); } >> >> @priority(1) >> function taskB() { doSomething(); } >> >> @priority(5) >> function taskC() { doSomething(); } >> >> taskManager.register(taskA, taskB, taskC); >> taskManager.run(); // run taking into account priority symbol of the >> functions >> >> // taskManager.js >> var priority = new Symbol(); >> >> function priority(p) { >> return function(target) { target[priority] = p; } >> } >> ``` >> >> On the contrary, you would want to replace a class completely: >> >> ``` >> @singleton >> class system { >> get version() { return '1.0.0'; } >> get drives() { return ...; } >> } >> >> console.log(system.version); >> >> function singleton(target) { >> return target(); >> } >> ``` >> >> I'm not saying is not important to distinguish between classes and >> functions, I'm just saying, it is not as important and not critical for the >> decorator syntax. It suffices for a framework to make their classes to >> inherit from a custom base object with a symbol `isClass` set to true to >> allow their own decorators to distinguish between classes and functions but >> these are specific-implementation details. What is true is the the syntax >> works for regular functions and class based functions. >> >> >>> >>> Maybe it's me overlooking at this, but the fact we cannot distinguish >>> between classes and functions doesn't feel right to me. >>> >> >> No, sorry, maybe it's me that I can not see a harmful side effect here. >> Can you point me some example where not distinguishing between functions >> and classes would be fatal, please? Maybe this way, I (and others) >> understand your concerns. >> >> >>> >>> Regards >>> >>> P.S. babel has some target (browsers mostly, and nodejs) but it >>> shouldn't be the reason to choose a pattern instead of another, or at least >>> not the only one >>> >> >> Of course, but it is a clear indicator of semantics. It's very valuable >> for a language to allow its own declarative semantics to be expressed in a >> programmatic fashion as it denotes a very consistent and versatile data & >> execution models. >> >> >>> >>> >>> >>> >>> >>> On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < >>> salva at unoyunodiez.com> wrote: >>> >>>> Hi people. >>>> >>>> After reading the conversation, I think there is no ambiguity at all >>>> or, may be, it must be there: decorating a function should be like >>>> decorating a class, you can not distinguish between them and that's all. >>>> Just look at the code generated in Babel: >>>> >>>> https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} >>>> <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> >>>> >>>> You'll see: >>>> >>>> ``` >>>> A = decorator(A) || A; >>>> ``` >>>> >>>> And this is the traditional notion of decorator we see in Python and >>>> other languages. A simple way to check for a generic decorator would be: >>>> >>>> ``` >>>> function decorator(target, name='', descriptor=null) { >>>> if (descriptor) console.log('Decorating a member'); >>>> else console.log('Decorating either a function or class'); >>>> } >>>> ``` >>>> >>>> And it's very consistent if you think the only difference a ES6 class >>>> introduces is that you are not allowed to call the class as a function. >>>> >>>> So, the generated code for: >>>> >>>> ``` >>>> @decorator >>>> function A() { } >>>> ``` >>>> >>>> Should be: >>>> >>>> ``` >>>> function A() {} >>>> A = decorator(A) || A; >>>> ``` >>>> >>>> And that's all, if you always add the overwrite after the definition, >>>> hoisting is irrelevant but if it worries you, simply avoid hoisting when >>>> decorating as Axel suggested. >>>> >>>> >>>> PS: Well thought, it must be possible for an hypothetical reflection >>>> function to determine if a function is a class or not as classes are marked >>>> to throw when they are not invoked with new. >>>> >>>> On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < >>>> andrea.giammarchi at gmail.com> wrote: >>>> >>>>> Ron, there's **no way** you can distinguish a class from a generic >>>>> function in current specifications. >>>>> >>>>> Having one argument won't tell me much, having a way to know that is >>>>> not a class I need to decorate (traits/mixins) but just a function, so >>>>> ignoring its prototype and do something else, would be cool but it's >>>>> unfortunately not possible or portable. >>>>> >>>>> How would you distinguish between a class or a function for a generic >>>>> decorator? Or all you are saying is that decorators shouldn't be able to >>>>> distinguish at all between a class, rather than a function? >>>>> >>>>> Regards >>>>> >>>>> >>>>> >>>>> >>>>> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton < >>>>> Ron.Buckton at microsoft.com> wrote: >>>>> >>>>>> Andrea, >>>>>> >>>>>> >>>>>> >>>>>> Is your concern about disambiguating the usage of a decorator at the >>>>>> call site or within the body of the decorator? In the current proposal, you >>>>>> can decorate a class member, or the class itself. >>>>>> >>>>>> >>>>>> >>>>>> When decorating a class member, three arguments are passed to the >>>>>> decorator: The target, the property key (string or symbol), and the >>>>>> descriptor. When decorating the class, one argument is passed to the >>>>>> decorator: The constructor function. Generally this means that you can >>>>>> disambiguate the usage of the decorator based simply on `arguments.length`, >>>>>> or testing for `undefined` for the property key or descriptor. >>>>>> >>>>>> >>>>>> >>>>>> Would it be better to have a more consistent way to disambiguate the >>>>>> usage of a decorator from within the decorator? This could be addressed >>>>>> with something like a Reflect.getDecoratorUsage API or a >>>>>> `function.decoration` meta-property or the like. Consider something like: >>>>>> >>>>>> >>>>>> >>>>>> ```js >>>>>> >>>>>> function memoize(target, key, descriptor) { >>>>>> >>>>>> switch (Reflect.getDecoratorUsage(arguments)) { >>>>>> >>>>>> case "class": >>>>>> >>>>>> // `target` is the class constructor. `key` and `descriptor` >>>>>> are undefined. >>>>>> >>>>>> >>>>>> >>>>>> case "function": >>>>>> >>>>>> // `target` is the function. `key` and `descriptor` are >>>>>> undefined. >>>>>> >>>>>> >>>>>> >>>>>> case "method": >>>>>> >>>>>> // `target` is the object containing the method (e.g. >>>>>> constructor >>>>>> >>>>>> // for a static method, prototype for a prototype method, or >>>>>> >>>>>> // instance for an object literal method). >>>>>> >>>>>> // `key` is the string or symbol property name for the method. >>>>>> >>>>>> // `descriptor` is the property descriptor for the method. >>>>>> >>>>>> >>>>>> >>>>>> case "accessor": >>>>>> >>>>>> // `target` is the object containing the accessor (e.g. >>>>>> constructor >>>>>> >>>>>> // for a static accessor, prototype for a prototype accessor, >>>>>> or >>>>>> >>>>>> // instance for an object literal accessor). >>>>>> >>>>>> // `key` is the string or symbol property name for the accessor. >>>>>> >>>>>> // `descriptor` is the property descriptor for the accessor. >>>>>> >>>>>> } >>>>>> >>>>>> } >>>>>> >>>>>> ``` >>>>>> >>>>>> >>>>>> >>>>>> Ron >>>>>> >>>>>> >>>>>> >>>>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On >>>>>> Behalf Of *Andrea Giammarchi >>>>>> *Sent:* Thursday, October 22, 2015 10:47 AM >>>>>> *To:* Yongxu Ren <renyongxu at gmail.com> >>>>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>>>>> *Subject:* Re: Decorators for functions >>>>>> >>>>>> >>>>>> >>>>>> Removing ambiguity is my point since the very first post: current >>>>>> proposal is about a target, a property name, and a descriptor for such >>>>>> property ... having functions/variables decorators have no target (in >>>>>> strict mode undefined can't be a target, right?) and not necessarily a >>>>>> descriptor, or if any, always a data one with fields that makes no sense >>>>>> (like enumerable within a private scope ... what does that even mean) >>>>>> >>>>>> >>>>>> >>>>>> I'm all in for a distinct, separate, syntax to decorate "callables" >>>>>> or other variables as long as the current proposal will make for ES7 and >>>>>> won't be bothered by this different requirement. >>>>>> >>>>>> >>>>>> >>>>>> Regards >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> >>>>>> wrote: >>>>>> >>>>>> I don't think >>>>>> >>>>>> >>>>>> >>>>>> > ```@@ or @() or @::meomize``` >>>>>> >>>>>> >>>>>> >>>>>> would really help much, you can tell what the decorator does by >>>>>> simply looking at its name. And looks like you can not use @ and @@ for the >>>>>> same decorator function without adding extra condition checking inside the >>>>>> function. >>>>>> >>>>>> >>>>>> >>>>>> There are two patterns that we have discussed here, they are actually >>>>>> quite distinct. I still think we should support decorator on variables, but >>>>>> maybe we should have 2 distinct syntax for the normal decorators and >>>>>> "ambient decorators"(from Jonathan's post): >>>>>> >>>>>> >>>>>> >>>>>> 1. decorator that alter the code behavior, the currently proposed >>>>>> decorator. Such as ```@memoize``` >>>>>> >>>>>> >>>>>> >>>>>> 2. decorator that absolutely does not alter the code behavior, only >>>>>> used for optimization, checking or debugging. Instead of @, a distinct >>>>>> syntax will be much clearer ex.```@annotatition@``` (Maybe it should >>>>>> be called annotation instead?): >>>>>> >>>>>> ``` >>>>>> >>>>>> @deprecated@ >>>>>> >>>>>> >>>>>> >>>>>> @number,number=>string@/*type checking*/ >>>>>> >>>>>> >>>>>> >>>>>> @debug("this message will only print in development mode")@ >>>>>> >>>>>> ``` >>>>>> >>>>>> >>>>>> >>>>>> it sounds like terrible idea to have a decorator in code that you can >>>>>> not figure out if it will alter the code behavior by looking at it. I do >>>>>> like to see all the new ideas been added into javascript, but it is also >>>>>> necessary to eliminate the ambiguity whenever possible. >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>>>>> jbondc at gdesolutions.com> wrote: >>>>>> >>>>>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>>>>> > > determined at creation time, allowing for massive engine >>>>>> optimization, >>>>>> > >>>>>> >>>>>> Ya I'm not sure from which hat "massive engine optimization" comes >>>>>> from? >>>>>> >>>>>> What's meant is likely using decorators as annotations (compile time >>>>>> optimizations hints): >>>>>> http://www.google.com/patents/US7013458 >>>>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>>>>> >>>>>> Or 'ambient decorators': >>>>>> >>>>>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>>>>> >>>>>> There's 2 patterns (maybe more?): >>>>>> (a) Tagging a 'tree transformation' on a node. >>>>>> (b) Metadata at compile time on a node. >>>>>> >>>>>> The thing about (b) is it can easily live outside of the code (like >>>>>> in typescript where you have an optional header/declaration file) >>>>>> >>>>>> With (a), it seems more conservative to see how it gets used with >>>>>> classes before bolting on to functions (opinion: end result in java is not >>>>>> something to be proud of). >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151023/b997e58c/attachment-0001.html>
On 22 October 2015 at 18:20, Jonathan Bond-Caron <jbondc at gdesolutions.com> wrote:
On Thu Oct 22 07:44 AM, Andreas Rossberg wrote:
determined at creation time, allowing for massive engine optimization,
Ya I'm not sure from which hat "massive engine optimization" comes from?
What's meant is likely using decorators as annotations (compile time optimizations hints): www.google.com/patents/US7013458
Note that this patent indeed defines declarative metadata annotations. That's the exact opposite of the imperative decorator proposal we are discussing right now, which completely conflates computation level and meta level and thus is pretty much unusable for compile-time hints.
On 22 October 2015 at 18:20, Jonathan Bond-Caron <jbondc at gdesolutions.com> wrote: > On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >> > determined at creation time, allowing for massive engine optimization, > > Ya I'm not sure from which hat "massive engine optimization" comes from? > > What's meant is likely using decorators as annotations (compile time optimizations hints): > http://www.google.com/patents/US7013458 Note that this patent indeed defines _declarative_ metadata annotations. That's the exact opposite of the imperative decorator proposal we are discussing right now, which completely conflates computation level and meta level and thus is pretty much unusable for compile-time hints. /Andreas > Or 'ambient decorators': > https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators > > There's 2 patterns (maybe more?): > (a) Tagging a 'tree transformation' on a node. > (b) Metadata at compile time on a node. > > The thing about (b) is it can easily live outside of the code (like in typescript where you have an optional header/declaration file) > > With (a), it seems more conservative to see how it gets used with classes before bolting on to functions (opinion: end result in java is not something to be proud of). >
On 22 October 2015 at 19:25, Jordan Harband <ljharb at gmail.com> wrote:
Andreas, thanks for correcting me on the optimization angle. I've been under that impression for awhile.
Are you saying that to achieve the optimization I envision, we'd need declarative syntax for descriptor properties (like enumerability etc), rather than function calls?
Yes, there would need to be a sufficient degree of phase separation, such that these annotations can be reliably gathered and inspected at compile time, and are known to be invariant at runtime.
On 22 October 2015 at 19:25, Jordan Harband <ljharb at gmail.com> wrote: > Andreas, thanks for correcting me on the optimization angle. I've been under > that impression for awhile. > > Are you saying that to achieve the optimization I envision, we'd need > declarative syntax for descriptor properties (like enumerability etc), > rather than function calls? Yes, there would need to be a sufficient degree of phase separation, such that these annotations can be reliably gathered and inspected at compile time, and are known to be invariant at runtime. /Andreas > On Thu, Oct 22, 2015 at 9:20 AM, Jonathan Bond-Caron > <jbondc at gdesolutions.com> wrote: >> >> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >> > > determined at creation time, allowing for massive engine optimization, >> > >> >> Ya I'm not sure from which hat "massive engine optimization" comes from? >> >> What's meant is likely using decorators as annotations (compile time >> optimizations hints): >> http://www.google.com/patents/US7013458 >> >> Or 'ambient decorators': >> >> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >> >> There's 2 patterns (maybe more?): >> (a) Tagging a 'tree transformation' on a node. >> (b) Metadata at compile time on a node. >> >> The thing about (b) is it can easily live outside of the code (like in >> typescript where you have an optional header/declaration file) >> >> With (a), it seems more conservative to see how it gets used with classes >> before bolting on to functions (opinion: end result in java is not something >> to be proud of). >> >
OK let me rephrase: it is not inter-operable with well known libraries that might have factories in the wild and no way to distinguish if they are dealing with new ES6 syntax or old one.
Having no way to distinguish easily breaks the web.
OK let me rephrase: it is **not inter-operable** with well known libraries that might have factories in the wild and no way to distinguish if they are dealing with new ES6 syntax or old one. Having no way to distinguish easily breaks the web. Regards On Fri, Oct 23, 2015 at 11:44 AM, Salvador de la Puente González < salva at unoyunodiez.com> wrote: > Well, I see, it's not worse than other dynamic typing issues (think about > `invokeThat.call()` being called on undefined or null, the exception only > gives you a runtime error and you could always wrap in a try-catch, see the > message and translate to yoour own exception or recover) but that does not > relate at all with decorators which is my point. I agree on > `Reflection.isClass` although I should check the spec in the search for > something related with that specific topic but returning to the previous > discussion about which syntax to use when decorating functions, I don't see > this is a blocker for extending present decorator syntax to functions. > > On Fri, Oct 23, 2015 at 12:17 PM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> well >> >> > Can you point me some example where not distinguishing between >> functions and classes would be fatal, please? >> >> the fact a class throws once invoked like a function isn't enough fatal >> to you? >> >> ```js >> function invokeThat() { >> var result = Object.create(this.prototype); >> return this.apply(result, arguments) || result; >> } >> >> invokeThat.call(function sum(a, b) { return a + b; }, 1, 2); // 3 >> >> invokeThat.call(class Point{constructor(x,y){this.x=x;this.y=y;}}, 10, >> 15); >> // Uncaught TypeError: Class constructors cannot be invoked without >> 'new'(…) >> ``` >> >> We are missing a `Reflection.isClass` ... useful or not, we've got two >> kind of "invokables" and nobody can distinguish from them. >> >> Regards >> >> >> >> >> On Fri, Oct 23, 2015 at 10:56 AM, Salvador de la Puente González < >> salva at unoyunodiez.com> wrote: >> >>> Hi Andrea. >>> >>> On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> which one is true? >>>> >>>> > I think there is no ambiguity at all ... decorating a function >>>> should be like decorating a class >>>> >>>> 'cause I think those are very different things. >>>> >>> >>> As far as I know, classes in ES6, apart from preventing you from calling >>> without `new` (and minor subclassing details), are identical to functions. >>> >>> >>>> You gonna wrap for sure the first one, you most likely ever even bother >>>> replacing the class, rather enriching its prototype or its public statics. >>>> >>> >>> Well, is not as sure you want to wrap a function at all. Suppose: >>> >>> ``` >>> // operaations.js >>> @priority(2) >>> function taskA() { doSomething(); } >>> >>> @priority(1) >>> function taskB() { doSomething(); } >>> >>> @priority(5) >>> function taskC() { doSomething(); } >>> >>> taskManager.register(taskA, taskB, taskC); >>> taskManager.run(); // run taking into account priority symbol of the >>> functions >>> >>> // taskManager.js >>> var priority = new Symbol(); >>> >>> function priority(p) { >>> return function(target) { target[priority] = p; } >>> } >>> ``` >>> >>> On the contrary, you would want to replace a class completely: >>> >>> ``` >>> @singleton >>> class system { >>> get version() { return '1.0.0'; } >>> get drives() { return ...; } >>> } >>> >>> console.log(system.version); >>> >>> function singleton(target) { >>> return target(); >>> } >>> ``` >>> >>> I'm not saying is not important to distinguish between classes and >>> functions, I'm just saying, it is not as important and not critical for the >>> decorator syntax. It suffices for a framework to make their classes to >>> inherit from a custom base object with a symbol `isClass` set to true to >>> allow their own decorators to distinguish between classes and functions but >>> these are specific-implementation details. What is true is the the syntax >>> works for regular functions and class based functions. >>> >>> >>>> >>>> Maybe it's me overlooking at this, but the fact we cannot distinguish >>>> between classes and functions doesn't feel right to me. >>>> >>> >>> No, sorry, maybe it's me that I can not see a harmful side effect here. >>> Can you point me some example where not distinguishing between functions >>> and classes would be fatal, please? Maybe this way, I (and others) >>> understand your concerns. >>> >>> >>>> >>>> Regards >>>> >>>> P.S. babel has some target (browsers mostly, and nodejs) but it >>>> shouldn't be the reason to choose a pattern instead of another, or at least >>>> not the only one >>>> >>> >>> Of course, but it is a clear indicator of semantics. It's very valuable >>> for a language to allow its own declarative semantics to be expressed in a >>> programmatic fashion as it denotes a very consistent and versatile data & >>> execution models. >>> >>> >>>> >>>> >>>> >>>> >>>> >>>> On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < >>>> salva at unoyunodiez.com> wrote: >>>> >>>>> Hi people. >>>>> >>>>> After reading the conversation, I think there is no ambiguity at all >>>>> or, may be, it must be there: decorating a function should be like >>>>> decorating a class, you can not distinguish between them and that's all. >>>>> Just look at the code generated in Babel: >>>>> >>>>> https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} >>>>> <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> >>>>> >>>>> You'll see: >>>>> >>>>> ``` >>>>> A = decorator(A) || A; >>>>> ``` >>>>> >>>>> And this is the traditional notion of decorator we see in Python and >>>>> other languages. A simple way to check for a generic decorator would be: >>>>> >>>>> ``` >>>>> function decorator(target, name='', descriptor=null) { >>>>> if (descriptor) console.log('Decorating a member'); >>>>> else console.log('Decorating either a function or class'); >>>>> } >>>>> ``` >>>>> >>>>> And it's very consistent if you think the only difference a ES6 class >>>>> introduces is that you are not allowed to call the class as a function. >>>>> >>>>> So, the generated code for: >>>>> >>>>> ``` >>>>> @decorator >>>>> function A() { } >>>>> ``` >>>>> >>>>> Should be: >>>>> >>>>> ``` >>>>> function A() {} >>>>> A = decorator(A) || A; >>>>> ``` >>>>> >>>>> And that's all, if you always add the overwrite after the definition, >>>>> hoisting is irrelevant but if it worries you, simply avoid hoisting when >>>>> decorating as Axel suggested. >>>>> >>>>> >>>>> PS: Well thought, it must be possible for an hypothetical reflection >>>>> function to determine if a function is a class or not as classes are marked >>>>> to throw when they are not invoked with new. >>>>> >>>>> On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < >>>>> andrea.giammarchi at gmail.com> wrote: >>>>> >>>>>> Ron, there's **no way** you can distinguish a class from a generic >>>>>> function in current specifications. >>>>>> >>>>>> Having one argument won't tell me much, having a way to know that is >>>>>> not a class I need to decorate (traits/mixins) but just a function, so >>>>>> ignoring its prototype and do something else, would be cool but it's >>>>>> unfortunately not possible or portable. >>>>>> >>>>>> How would you distinguish between a class or a function for a generic >>>>>> decorator? Or all you are saying is that decorators shouldn't be able to >>>>>> distinguish at all between a class, rather than a function? >>>>>> >>>>>> Regards >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton < >>>>>> Ron.Buckton at microsoft.com> wrote: >>>>>> >>>>>>> Andrea, >>>>>>> >>>>>>> >>>>>>> >>>>>>> Is your concern about disambiguating the usage of a decorator at the >>>>>>> call site or within the body of the decorator? In the current proposal, you >>>>>>> can decorate a class member, or the class itself. >>>>>>> >>>>>>> >>>>>>> >>>>>>> When decorating a class member, three arguments are passed to the >>>>>>> decorator: The target, the property key (string or symbol), and the >>>>>>> descriptor. When decorating the class, one argument is passed to the >>>>>>> decorator: The constructor function. Generally this means that you can >>>>>>> disambiguate the usage of the decorator based simply on `arguments.length`, >>>>>>> or testing for `undefined` for the property key or descriptor. >>>>>>> >>>>>>> >>>>>>> >>>>>>> Would it be better to have a more consistent way to disambiguate the >>>>>>> usage of a decorator from within the decorator? This could be addressed >>>>>>> with something like a Reflect.getDecoratorUsage API or a >>>>>>> `function.decoration` meta-property or the like. Consider something like: >>>>>>> >>>>>>> >>>>>>> >>>>>>> ```js >>>>>>> >>>>>>> function memoize(target, key, descriptor) { >>>>>>> >>>>>>> switch (Reflect.getDecoratorUsage(arguments)) { >>>>>>> >>>>>>> case "class": >>>>>>> >>>>>>> // `target` is the class constructor. `key` and `descriptor` >>>>>>> are undefined. >>>>>>> >>>>>>> >>>>>>> >>>>>>> case "function": >>>>>>> >>>>>>> // `target` is the function. `key` and `descriptor` are >>>>>>> undefined. >>>>>>> >>>>>>> >>>>>>> >>>>>>> case "method": >>>>>>> >>>>>>> // `target` is the object containing the method (e.g. >>>>>>> constructor >>>>>>> >>>>>>> // for a static method, prototype for a prototype method, or >>>>>>> >>>>>>> // instance for an object literal method). >>>>>>> >>>>>>> // `key` is the string or symbol property name for the method. >>>>>>> >>>>>>> // `descriptor` is the property descriptor for the method. >>>>>>> >>>>>>> >>>>>>> >>>>>>> case "accessor": >>>>>>> >>>>>>> // `target` is the object containing the accessor (e.g. >>>>>>> constructor >>>>>>> >>>>>>> // for a static accessor, prototype for a prototype accessor, >>>>>>> or >>>>>>> >>>>>>> // instance for an object literal accessor). >>>>>>> >>>>>>> // `key` is the string or symbol property name for the >>>>>>> accessor. >>>>>>> >>>>>>> // `descriptor` is the property descriptor for the accessor. >>>>>>> >>>>>>> } >>>>>>> >>>>>>> } >>>>>>> >>>>>>> ``` >>>>>>> >>>>>>> >>>>>>> >>>>>>> Ron >>>>>>> >>>>>>> >>>>>>> >>>>>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On >>>>>>> Behalf Of *Andrea Giammarchi >>>>>>> *Sent:* Thursday, October 22, 2015 10:47 AM >>>>>>> *To:* Yongxu Ren <renyongxu at gmail.com> >>>>>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>>>>>> *Subject:* Re: Decorators for functions >>>>>>> >>>>>>> >>>>>>> >>>>>>> Removing ambiguity is my point since the very first post: current >>>>>>> proposal is about a target, a property name, and a descriptor for such >>>>>>> property ... having functions/variables decorators have no target (in >>>>>>> strict mode undefined can't be a target, right?) and not necessarily a >>>>>>> descriptor, or if any, always a data one with fields that makes no sense >>>>>>> (like enumerable within a private scope ... what does that even mean) >>>>>>> >>>>>>> >>>>>>> >>>>>>> I'm all in for a distinct, separate, syntax to decorate "callables" >>>>>>> or other variables as long as the current proposal will make for ES7 and >>>>>>> won't be bothered by this different requirement. >>>>>>> >>>>>>> >>>>>>> >>>>>>> Regards >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> >>>>>>> wrote: >>>>>>> >>>>>>> I don't think >>>>>>> >>>>>>> >>>>>>> >>>>>>> > ```@@ or @() or @::meomize``` >>>>>>> >>>>>>> >>>>>>> >>>>>>> would really help much, you can tell what the decorator does by >>>>>>> simply looking at its name. And looks like you can not use @ and @@ for the >>>>>>> same decorator function without adding extra condition checking inside the >>>>>>> function. >>>>>>> >>>>>>> >>>>>>> >>>>>>> There are two patterns that we have discussed here, they are >>>>>>> actually quite distinct. I still think we should support decorator on >>>>>>> variables, but maybe we should have 2 distinct syntax for the normal >>>>>>> decorators and "ambient decorators"(from Jonathan's post): >>>>>>> >>>>>>> >>>>>>> >>>>>>> 1. decorator that alter the code behavior, the currently proposed >>>>>>> decorator. Such as ```@memoize``` >>>>>>> >>>>>>> >>>>>>> >>>>>>> 2. decorator that absolutely does not alter the code behavior, only >>>>>>> used for optimization, checking or debugging. Instead of @, a distinct >>>>>>> syntax will be much clearer ex.```@annotatition@``` (Maybe it >>>>>>> should be called annotation instead?): >>>>>>> >>>>>>> ``` >>>>>>> >>>>>>> @deprecated@ >>>>>>> >>>>>>> >>>>>>> >>>>>>> @number,number=>string@/*type checking*/ >>>>>>> >>>>>>> >>>>>>> >>>>>>> @debug("this message will only print in development mode")@ >>>>>>> >>>>>>> ``` >>>>>>> >>>>>>> >>>>>>> >>>>>>> it sounds like terrible idea to have a decorator in code that you >>>>>>> can not figure out if it will alter the code behavior by looking at it. I >>>>>>> do like to see all the new ideas been added into javascript, but it is also >>>>>>> necessary to eliminate the ambiguity whenever possible. >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>>>>>> jbondc at gdesolutions.com> wrote: >>>>>>> >>>>>>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>>>>>> > > determined at creation time, allowing for massive engine >>>>>>> optimization, >>>>>>> > >>>>>>> >>>>>>> Ya I'm not sure from which hat "massive engine optimization" comes >>>>>>> from? >>>>>>> >>>>>>> What's meant is likely using decorators as annotations (compile time >>>>>>> optimizations hints): >>>>>>> http://www.google.com/patents/US7013458 >>>>>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>>>>>> >>>>>>> Or 'ambient decorators': >>>>>>> >>>>>>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>>>>>> >>>>>>> There's 2 patterns (maybe more?): >>>>>>> (a) Tagging a 'tree transformation' on a node. >>>>>>> (b) Metadata at compile time on a node. >>>>>>> >>>>>>> The thing about (b) is it can easily live outside of the code (like >>>>>>> in typescript where you have an optional header/declaration file) >>>>>>> >>>>>>> With (a), it seems more conservative to see how it gets used with >>>>>>> classes before bolting on to functions (opinion: end result in java is not >>>>>>> something to be proud of). >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151023/cb9da3b2/attachment-0001.html>
No, sorry, I don't think so. Maybe I don't get your point so could you provide an example of how decorators on functions could break the web?
As far as I understand, if you start to use foreign code beyond its API you could break the old code with and without decorators.
No, sorry, I don't think so. Maybe I don't get your point so could you provide an example of how decorators on functions could break the web? As far as I understand, if you start to use foreign code beyond its API you could break the old code with and without decorators. On Fri, Oct 23, 2015 at 1:52 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote: > OK let me rephrase: it is **not inter-operable** with well known libraries > that might have factories in the wild and no way to distinguish if they are > dealing with new ES6 syntax or old one. > > Having no way to distinguish easily breaks the web. > > Regards > > On Fri, Oct 23, 2015 at 11:44 AM, Salvador de la Puente González < > salva at unoyunodiez.com> wrote: > >> Well, I see, it's not worse than other dynamic typing issues (think about >> `invokeThat.call()` being called on undefined or null, the exception only >> gives you a runtime error and you could always wrap in a try-catch, see the >> message and translate to yoour own exception or recover) but that does not >> relate at all with decorators which is my point. I agree on >> `Reflection.isClass` although I should check the spec in the search for >> something related with that specific topic but returning to the previous >> discussion about which syntax to use when decorating functions, I don't see >> this is a blocker for extending present decorator syntax to functions. >> >> On Fri, Oct 23, 2015 at 12:17 PM, Andrea Giammarchi < >> andrea.giammarchi at gmail.com> wrote: >> >>> well >>> >>> > Can you point me some example where not distinguishing between >>> functions and classes would be fatal, please? >>> >>> the fact a class throws once invoked like a function isn't enough fatal >>> to you? >>> >>> ```js >>> function invokeThat() { >>> var result = Object.create(this.prototype); >>> return this.apply(result, arguments) || result; >>> } >>> >>> invokeThat.call(function sum(a, b) { return a + b; }, 1, 2); // 3 >>> >>> invokeThat.call(class Point{constructor(x,y){this.x=x;this.y=y;}}, 10, >>> 15); >>> // Uncaught TypeError: Class constructors cannot be invoked without >>> 'new'(…) >>> ``` >>> >>> We are missing a `Reflection.isClass` ... useful or not, we've got two >>> kind of "invokables" and nobody can distinguish from them. >>> >>> Regards >>> >>> >>> >>> >>> On Fri, Oct 23, 2015 at 10:56 AM, Salvador de la Puente González < >>> salva at unoyunodiez.com> wrote: >>> >>>> Hi Andrea. >>>> >>>> On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < >>>> andrea.giammarchi at gmail.com> wrote: >>>> >>>>> which one is true? >>>>> >>>>> > I think there is no ambiguity at all ... decorating a function >>>>> should be like decorating a class >>>>> >>>>> 'cause I think those are very different things. >>>>> >>>> >>>> As far as I know, classes in ES6, apart from preventing you from >>>> calling without `new` (and minor subclassing details), are identical to >>>> functions. >>>> >>>> >>>>> You gonna wrap for sure the first one, you most likely ever even >>>>> bother replacing the class, rather enriching its prototype or its public >>>>> statics. >>>>> >>>> >>>> Well, is not as sure you want to wrap a function at all. Suppose: >>>> >>>> ``` >>>> // operaations.js >>>> @priority(2) >>>> function taskA() { doSomething(); } >>>> >>>> @priority(1) >>>> function taskB() { doSomething(); } >>>> >>>> @priority(5) >>>> function taskC() { doSomething(); } >>>> >>>> taskManager.register(taskA, taskB, taskC); >>>> taskManager.run(); // run taking into account priority symbol of the >>>> functions >>>> >>>> // taskManager.js >>>> var priority = new Symbol(); >>>> >>>> function priority(p) { >>>> return function(target) { target[priority] = p; } >>>> } >>>> ``` >>>> >>>> On the contrary, you would want to replace a class completely: >>>> >>>> ``` >>>> @singleton >>>> class system { >>>> get version() { return '1.0.0'; } >>>> get drives() { return ...; } >>>> } >>>> >>>> console.log(system.version); >>>> >>>> function singleton(target) { >>>> return target(); >>>> } >>>> ``` >>>> >>>> I'm not saying is not important to distinguish between classes and >>>> functions, I'm just saying, it is not as important and not critical for the >>>> decorator syntax. It suffices for a framework to make their classes to >>>> inherit from a custom base object with a symbol `isClass` set to true to >>>> allow their own decorators to distinguish between classes and functions but >>>> these are specific-implementation details. What is true is the the syntax >>>> works for regular functions and class based functions. >>>> >>>> >>>>> >>>>> Maybe it's me overlooking at this, but the fact we cannot distinguish >>>>> between classes and functions doesn't feel right to me. >>>>> >>>> >>>> No, sorry, maybe it's me that I can not see a harmful side effect here. >>>> Can you point me some example where not distinguishing between functions >>>> and classes would be fatal, please? Maybe this way, I (and others) >>>> understand your concerns. >>>> >>>> >>>>> >>>>> Regards >>>>> >>>>> P.S. babel has some target (browsers mostly, and nodejs) but it >>>>> shouldn't be the reason to choose a pattern instead of another, or at least >>>>> not the only one >>>>> >>>> >>>> Of course, but it is a clear indicator of semantics. It's very valuable >>>> for a language to allow its own declarative semantics to be expressed in a >>>> programmatic fashion as it denotes a very consistent and versatile data & >>>> execution models. >>>> >>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < >>>>> salva at unoyunodiez.com> wrote: >>>>> >>>>>> Hi people. >>>>>> >>>>>> After reading the conversation, I think there is no ambiguity at all >>>>>> or, may be, it must be there: decorating a function should be like >>>>>> decorating a class, you can not distinguish between them and that's all. >>>>>> Just look at the code generated in Babel: >>>>>> >>>>>> https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} >>>>>> <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> >>>>>> >>>>>> You'll see: >>>>>> >>>>>> ``` >>>>>> A = decorator(A) || A; >>>>>> ``` >>>>>> >>>>>> And this is the traditional notion of decorator we see in Python and >>>>>> other languages. A simple way to check for a generic decorator would be: >>>>>> >>>>>> ``` >>>>>> function decorator(target, name='', descriptor=null) { >>>>>> if (descriptor) console.log('Decorating a member'); >>>>>> else console.log('Decorating either a function or class'); >>>>>> } >>>>>> ``` >>>>>> >>>>>> And it's very consistent if you think the only difference a ES6 class >>>>>> introduces is that you are not allowed to call the class as a function. >>>>>> >>>>>> So, the generated code for: >>>>>> >>>>>> ``` >>>>>> @decorator >>>>>> function A() { } >>>>>> ``` >>>>>> >>>>>> Should be: >>>>>> >>>>>> ``` >>>>>> function A() {} >>>>>> A = decorator(A) || A; >>>>>> ``` >>>>>> >>>>>> And that's all, if you always add the overwrite after the definition, >>>>>> hoisting is irrelevant but if it worries you, simply avoid hoisting when >>>>>> decorating as Axel suggested. >>>>>> >>>>>> >>>>>> PS: Well thought, it must be possible for an hypothetical reflection >>>>>> function to determine if a function is a class or not as classes are marked >>>>>> to throw when they are not invoked with new. >>>>>> >>>>>> On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < >>>>>> andrea.giammarchi at gmail.com> wrote: >>>>>> >>>>>>> Ron, there's **no way** you can distinguish a class from a generic >>>>>>> function in current specifications. >>>>>>> >>>>>>> Having one argument won't tell me much, having a way to know that is >>>>>>> not a class I need to decorate (traits/mixins) but just a function, so >>>>>>> ignoring its prototype and do something else, would be cool but it's >>>>>>> unfortunately not possible or portable. >>>>>>> >>>>>>> How would you distinguish between a class or a function for a >>>>>>> generic decorator? Or all you are saying is that decorators shouldn't be >>>>>>> able to distinguish at all between a class, rather than a function? >>>>>>> >>>>>>> Regards >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton < >>>>>>> Ron.Buckton at microsoft.com> wrote: >>>>>>> >>>>>>>> Andrea, >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Is your concern about disambiguating the usage of a decorator at >>>>>>>> the call site or within the body of the decorator? In the current proposal, >>>>>>>> you can decorate a class member, or the class itself. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> When decorating a class member, three arguments are passed to the >>>>>>>> decorator: The target, the property key (string or symbol), and the >>>>>>>> descriptor. When decorating the class, one argument is passed to the >>>>>>>> decorator: The constructor function. Generally this means that you can >>>>>>>> disambiguate the usage of the decorator based simply on `arguments.length`, >>>>>>>> or testing for `undefined` for the property key or descriptor. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Would it be better to have a more consistent way to disambiguate >>>>>>>> the usage of a decorator from within the decorator? This could be addressed >>>>>>>> with something like a Reflect.getDecoratorUsage API or a >>>>>>>> `function.decoration` meta-property or the like. Consider something like: >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> ```js >>>>>>>> >>>>>>>> function memoize(target, key, descriptor) { >>>>>>>> >>>>>>>> switch (Reflect.getDecoratorUsage(arguments)) { >>>>>>>> >>>>>>>> case "class": >>>>>>>> >>>>>>>> // `target` is the class constructor. `key` and `descriptor` >>>>>>>> are undefined. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> case "function": >>>>>>>> >>>>>>>> // `target` is the function. `key` and `descriptor` are >>>>>>>> undefined. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> case "method": >>>>>>>> >>>>>>>> // `target` is the object containing the method (e.g. >>>>>>>> constructor >>>>>>>> >>>>>>>> // for a static method, prototype for a prototype method, or >>>>>>>> >>>>>>>> // instance for an object literal method). >>>>>>>> >>>>>>>> // `key` is the string or symbol property name for the method. >>>>>>>> >>>>>>>> // `descriptor` is the property descriptor for the method. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> case "accessor": >>>>>>>> >>>>>>>> // `target` is the object containing the accessor (e.g. >>>>>>>> constructor >>>>>>>> >>>>>>>> // for a static accessor, prototype for a prototype accessor, >>>>>>>> or >>>>>>>> >>>>>>>> // instance for an object literal accessor). >>>>>>>> >>>>>>>> // `key` is the string or symbol property name for the >>>>>>>> accessor. >>>>>>>> >>>>>>>> // `descriptor` is the property descriptor for the accessor. >>>>>>>> >>>>>>>> } >>>>>>>> >>>>>>>> } >>>>>>>> >>>>>>>> ``` >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Ron >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On >>>>>>>> Behalf Of *Andrea Giammarchi >>>>>>>> *Sent:* Thursday, October 22, 2015 10:47 AM >>>>>>>> *To:* Yongxu Ren <renyongxu at gmail.com> >>>>>>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>>>>>>> *Subject:* Re: Decorators for functions >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Removing ambiguity is my point since the very first post: current >>>>>>>> proposal is about a target, a property name, and a descriptor for such >>>>>>>> property ... having functions/variables decorators have no target (in >>>>>>>> strict mode undefined can't be a target, right?) and not necessarily a >>>>>>>> descriptor, or if any, always a data one with fields that makes no sense >>>>>>>> (like enumerable within a private scope ... what does that even mean) >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> I'm all in for a distinct, separate, syntax to decorate "callables" >>>>>>>> or other variables as long as the current proposal will make for ES7 and >>>>>>>> won't be bothered by this different requirement. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Regards >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> >>>>>>>> wrote: >>>>>>>> >>>>>>>> I don't think >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> > ```@@ or @() or @::meomize``` >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> would really help much, you can tell what the decorator does by >>>>>>>> simply looking at its name. And looks like you can not use @ and @@ for the >>>>>>>> same decorator function without adding extra condition checking inside the >>>>>>>> function. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> There are two patterns that we have discussed here, they are >>>>>>>> actually quite distinct. I still think we should support decorator on >>>>>>>> variables, but maybe we should have 2 distinct syntax for the normal >>>>>>>> decorators and "ambient decorators"(from Jonathan's post): >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> 1. decorator that alter the code behavior, the currently proposed >>>>>>>> decorator. Such as ```@memoize``` >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> 2. decorator that absolutely does not alter the code behavior, only >>>>>>>> used for optimization, checking or debugging. Instead of @, a distinct >>>>>>>> syntax will be much clearer ex.```@annotatition@``` (Maybe it >>>>>>>> should be called annotation instead?): >>>>>>>> >>>>>>>> ``` >>>>>>>> >>>>>>>> @deprecated@ >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> @number,number=>string@/*type checking*/ >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> @debug("this message will only print in development mode")@ >>>>>>>> >>>>>>>> ``` >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> it sounds like terrible idea to have a decorator in code that you >>>>>>>> can not figure out if it will alter the code behavior by looking at it. I >>>>>>>> do like to see all the new ideas been added into javascript, but it is also >>>>>>>> necessary to eliminate the ambiguity whenever possible. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>>>>>>> jbondc at gdesolutions.com> wrote: >>>>>>>> >>>>>>>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>>>>>>> > > determined at creation time, allowing for massive engine >>>>>>>> optimization, >>>>>>>> > >>>>>>>> >>>>>>>> Ya I'm not sure from which hat "massive engine optimization" comes >>>>>>>> from? >>>>>>>> >>>>>>>> What's meant is likely using decorators as annotations (compile >>>>>>>> time optimizations hints): >>>>>>>> http://www.google.com/patents/US7013458 >>>>>>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>>>>>>> >>>>>>>> Or 'ambient decorators': >>>>>>>> >>>>>>>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>>>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>>>>>>> >>>>>>>> There's 2 patterns (maybe more?): >>>>>>>> (a) Tagging a 'tree transformation' on a node. >>>>>>>> (b) Metadata at compile time on a node. >>>>>>>> >>>>>>>> The thing about (b) is it can easily live outside of the code (like >>>>>>>> in typescript where you have an optional header/declaration file) >>>>>>>> >>>>>>>> With (a), it seems more conservative to see how it gets used with >>>>>>>> classes before bolting on to functions (opinion: end result in java is not >>>>>>>> something to be proud of). >>>>>>>> >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151023/b7daf93c/attachment-0001.html>
Salvador
could you provide an example of how decorators on functions could break
the web?
we were talking about the ability to distinguish, not anymore about decorators. I think this thread went off topic so ... let's see what TC39 will decide.
Salvador > could you provide an example of how decorators on functions could break the web? we were talking about the ability to distinguish, not anymore about decorators. I think this thread went off topic so ... let's see what TC39 will decide. Cheers On Fri, Oct 23, 2015 at 2:25 PM, Salvador de la Puente González < salva at unoyunodiez.com> wrote: > No, sorry, I don't think so. Maybe I don't get your point so could you > provide an example of how decorators on functions could break the web? > > As far as I understand, if you start to use foreign code beyond its API > you could break the old code with and without decorators. > > On Fri, Oct 23, 2015 at 1:52 PM, Andrea Giammarchi < > andrea.giammarchi at gmail.com> wrote: > >> OK let me rephrase: it is **not inter-operable** with well known >> libraries that might have factories in the wild and no way to distinguish >> if they are dealing with new ES6 syntax or old one. >> >> Having no way to distinguish easily breaks the web. >> >> Regards >> >> On Fri, Oct 23, 2015 at 11:44 AM, Salvador de la Puente González < >> salva at unoyunodiez.com> wrote: >> >>> Well, I see, it's not worse than other dynamic typing issues (think >>> about `invokeThat.call()` being called on undefined or null, the exception >>> only gives you a runtime error and you could always wrap in a try-catch, >>> see the message and translate to yoour own exception or recover) but that >>> does not relate at all with decorators which is my point. I agree on >>> `Reflection.isClass` although I should check the spec in the search for >>> something related with that specific topic but returning to the previous >>> discussion about which syntax to use when decorating functions, I don't see >>> this is a blocker for extending present decorator syntax to functions. >>> >>> On Fri, Oct 23, 2015 at 12:17 PM, Andrea Giammarchi < >>> andrea.giammarchi at gmail.com> wrote: >>> >>>> well >>>> >>>> > Can you point me some example where not distinguishing between >>>> functions and classes would be fatal, please? >>>> >>>> the fact a class throws once invoked like a function isn't enough fatal >>>> to you? >>>> >>>> ```js >>>> function invokeThat() { >>>> var result = Object.create(this.prototype); >>>> return this.apply(result, arguments) || result; >>>> } >>>> >>>> invokeThat.call(function sum(a, b) { return a + b; }, 1, 2); // 3 >>>> >>>> invokeThat.call(class Point{constructor(x,y){this.x=x;this.y=y;}}, 10, >>>> 15); >>>> // Uncaught TypeError: Class constructors cannot be invoked without >>>> 'new'(…) >>>> ``` >>>> >>>> We are missing a `Reflection.isClass` ... useful or not, we've got two >>>> kind of "invokables" and nobody can distinguish from them. >>>> >>>> Regards >>>> >>>> >>>> >>>> >>>> On Fri, Oct 23, 2015 at 10:56 AM, Salvador de la Puente González < >>>> salva at unoyunodiez.com> wrote: >>>> >>>>> Hi Andrea. >>>>> >>>>> On Thu, Oct 22, 2015 at 10:34 PM, Andrea Giammarchi < >>>>> andrea.giammarchi at gmail.com> wrote: >>>>> >>>>>> which one is true? >>>>>> >>>>>> > I think there is no ambiguity at all ... decorating a function >>>>>> should be like decorating a class >>>>>> >>>>>> 'cause I think those are very different things. >>>>>> >>>>> >>>>> As far as I know, classes in ES6, apart from preventing you from >>>>> calling without `new` (and minor subclassing details), are identical to >>>>> functions. >>>>> >>>>> >>>>>> You gonna wrap for sure the first one, you most likely ever even >>>>>> bother replacing the class, rather enriching its prototype or its public >>>>>> statics. >>>>>> >>>>> >>>>> Well, is not as sure you want to wrap a function at all. Suppose: >>>>> >>>>> ``` >>>>> // operaations.js >>>>> @priority(2) >>>>> function taskA() { doSomething(); } >>>>> >>>>> @priority(1) >>>>> function taskB() { doSomething(); } >>>>> >>>>> @priority(5) >>>>> function taskC() { doSomething(); } >>>>> >>>>> taskManager.register(taskA, taskB, taskC); >>>>> taskManager.run(); // run taking into account priority symbol of the >>>>> functions >>>>> >>>>> // taskManager.js >>>>> var priority = new Symbol(); >>>>> >>>>> function priority(p) { >>>>> return function(target) { target[priority] = p; } >>>>> } >>>>> ``` >>>>> >>>>> On the contrary, you would want to replace a class completely: >>>>> >>>>> ``` >>>>> @singleton >>>>> class system { >>>>> get version() { return '1.0.0'; } >>>>> get drives() { return ...; } >>>>> } >>>>> >>>>> console.log(system.version); >>>>> >>>>> function singleton(target) { >>>>> return target(); >>>>> } >>>>> ``` >>>>> >>>>> I'm not saying is not important to distinguish between classes and >>>>> functions, I'm just saying, it is not as important and not critical for the >>>>> decorator syntax. It suffices for a framework to make their classes to >>>>> inherit from a custom base object with a symbol `isClass` set to true to >>>>> allow their own decorators to distinguish between classes and functions but >>>>> these are specific-implementation details. What is true is the the syntax >>>>> works for regular functions and class based functions. >>>>> >>>>> >>>>>> >>>>>> Maybe it's me overlooking at this, but the fact we cannot distinguish >>>>>> between classes and functions doesn't feel right to me. >>>>>> >>>>> >>>>> No, sorry, maybe it's me that I can not see a harmful side effect >>>>> here. Can you point me some example where not distinguishing between >>>>> functions and classes would be fatal, please? Maybe this way, I (and >>>>> others) understand your concerns. >>>>> >>>>> >>>>>> >>>>>> Regards >>>>>> >>>>>> P.S. babel has some target (browsers mostly, and nodejs) but it >>>>>> shouldn't be the reason to choose a pattern instead of another, or at least >>>>>> not the only one >>>>>> >>>>> >>>>> Of course, but it is a clear indicator of semantics. It's very >>>>> valuable for a language to allow its own declarative semantics to be >>>>> expressed in a programmatic fashion as it denotes a very consistent and >>>>> versatile data & execution models. >>>>> >>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Thu, Oct 22, 2015 at 9:26 PM, Salvador de la Puente González < >>>>>> salva at unoyunodiez.com> wrote: >>>>>> >>>>>>> Hi people. >>>>>>> >>>>>>> After reading the conversation, I think there is no ambiguity at all >>>>>>> or, may be, it must be there: decorating a function should be like >>>>>>> decorating a class, you can not distinguish between them and that's all. >>>>>>> Just look at the code generated in Babel: >>>>>>> >>>>>>> https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20{} >>>>>>> <https://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&code=%40decorator%0Aclass%20A%20%7B%7D> >>>>>>> >>>>>>> You'll see: >>>>>>> >>>>>>> ``` >>>>>>> A = decorator(A) || A; >>>>>>> ``` >>>>>>> >>>>>>> And this is the traditional notion of decorator we see in Python and >>>>>>> other languages. A simple way to check for a generic decorator would be: >>>>>>> >>>>>>> ``` >>>>>>> function decorator(target, name='', descriptor=null) { >>>>>>> if (descriptor) console.log('Decorating a member'); >>>>>>> else console.log('Decorating either a function or class'); >>>>>>> } >>>>>>> ``` >>>>>>> >>>>>>> And it's very consistent if you think the only difference a ES6 >>>>>>> class introduces is that you are not allowed to call the class as a >>>>>>> function. >>>>>>> >>>>>>> So, the generated code for: >>>>>>> >>>>>>> ``` >>>>>>> @decorator >>>>>>> function A() { } >>>>>>> ``` >>>>>>> >>>>>>> Should be: >>>>>>> >>>>>>> ``` >>>>>>> function A() {} >>>>>>> A = decorator(A) || A; >>>>>>> ``` >>>>>>> >>>>>>> And that's all, if you always add the overwrite after the >>>>>>> definition, hoisting is irrelevant but if it worries you, simply avoid >>>>>>> hoisting when decorating as Axel suggested. >>>>>>> >>>>>>> >>>>>>> PS: Well thought, it must be possible for an hypothetical reflection >>>>>>> function to determine if a function is a class or not as classes are marked >>>>>>> to throw when they are not invoked with new. >>>>>>> >>>>>>> On Thu, Oct 22, 2015 at 9:52 PM, Andrea Giammarchi < >>>>>>> andrea.giammarchi at gmail.com> wrote: >>>>>>> >>>>>>>> Ron, there's **no way** you can distinguish a class from a generic >>>>>>>> function in current specifications. >>>>>>>> >>>>>>>> Having one argument won't tell me much, having a way to know that >>>>>>>> is not a class I need to decorate (traits/mixins) but just a function, so >>>>>>>> ignoring its prototype and do something else, would be cool but it's >>>>>>>> unfortunately not possible or portable. >>>>>>>> >>>>>>>> How would you distinguish between a class or a function for a >>>>>>>> generic decorator? Or all you are saying is that decorators shouldn't be >>>>>>>> able to distinguish at all between a class, rather than a function? >>>>>>>> >>>>>>>> Regards >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Thu, Oct 22, 2015 at 7:32 PM, Ron Buckton < >>>>>>>> Ron.Buckton at microsoft.com> wrote: >>>>>>>> >>>>>>>>> Andrea, >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Is your concern about disambiguating the usage of a decorator at >>>>>>>>> the call site or within the body of the decorator? In the current proposal, >>>>>>>>> you can decorate a class member, or the class itself. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> When decorating a class member, three arguments are passed to the >>>>>>>>> decorator: The target, the property key (string or symbol), and the >>>>>>>>> descriptor. When decorating the class, one argument is passed to the >>>>>>>>> decorator: The constructor function. Generally this means that you can >>>>>>>>> disambiguate the usage of the decorator based simply on `arguments.length`, >>>>>>>>> or testing for `undefined` for the property key or descriptor. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Would it be better to have a more consistent way to disambiguate >>>>>>>>> the usage of a decorator from within the decorator? This could be addressed >>>>>>>>> with something like a Reflect.getDecoratorUsage API or a >>>>>>>>> `function.decoration` meta-property or the like. Consider something like: >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> ```js >>>>>>>>> >>>>>>>>> function memoize(target, key, descriptor) { >>>>>>>>> >>>>>>>>> switch (Reflect.getDecoratorUsage(arguments)) { >>>>>>>>> >>>>>>>>> case "class": >>>>>>>>> >>>>>>>>> // `target` is the class constructor. `key` and `descriptor` >>>>>>>>> are undefined. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> case "function": >>>>>>>>> >>>>>>>>> // `target` is the function. `key` and `descriptor` are >>>>>>>>> undefined. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> case "method": >>>>>>>>> >>>>>>>>> // `target` is the object containing the method (e.g. >>>>>>>>> constructor >>>>>>>>> >>>>>>>>> // for a static method, prototype for a prototype method, or >>>>>>>>> >>>>>>>>> // instance for an object literal method). >>>>>>>>> >>>>>>>>> // `key` is the string or symbol property name for the >>>>>>>>> method. >>>>>>>>> >>>>>>>>> // `descriptor` is the property descriptor for the method. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> case "accessor": >>>>>>>>> >>>>>>>>> // `target` is the object containing the accessor (e.g. >>>>>>>>> constructor >>>>>>>>> >>>>>>>>> // for a static accessor, prototype for a prototype >>>>>>>>> accessor, or >>>>>>>>> >>>>>>>>> // instance for an object literal accessor). >>>>>>>>> >>>>>>>>> // `key` is the string or symbol property name for the >>>>>>>>> accessor. >>>>>>>>> >>>>>>>>> // `descriptor` is the property descriptor for the accessor. >>>>>>>>> >>>>>>>>> } >>>>>>>>> >>>>>>>>> } >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Ron >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> *From:* es-discuss [mailto:es-discuss-bounces at mozilla.org] *On >>>>>>>>> Behalf Of *Andrea Giammarchi >>>>>>>>> *Sent:* Thursday, October 22, 2015 10:47 AM >>>>>>>>> *To:* Yongxu Ren <renyongxu at gmail.com> >>>>>>>>> *Cc:* es-discuss mailing list <es-discuss at mozilla.org> >>>>>>>>> *Subject:* Re: Decorators for functions >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Removing ambiguity is my point since the very first post: current >>>>>>>>> proposal is about a target, a property name, and a descriptor for such >>>>>>>>> property ... having functions/variables decorators have no target (in >>>>>>>>> strict mode undefined can't be a target, right?) and not necessarily a >>>>>>>>> descriptor, or if any, always a data one with fields that makes no sense >>>>>>>>> (like enumerable within a private scope ... what does that even mean) >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> I'm all in for a distinct, separate, syntax to decorate >>>>>>>>> "callables" or other variables as long as the current proposal will make >>>>>>>>> for ES7 and won't be bothered by this different requirement. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Regards >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren <renyongxu at gmail.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>> I don't think >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> > ```@@ or @() or @::meomize``` >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> would really help much, you can tell what the decorator does by >>>>>>>>> simply looking at its name. And looks like you can not use @ and @@ for the >>>>>>>>> same decorator function without adding extra condition checking inside the >>>>>>>>> function. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> There are two patterns that we have discussed here, they are >>>>>>>>> actually quite distinct. I still think we should support decorator on >>>>>>>>> variables, but maybe we should have 2 distinct syntax for the normal >>>>>>>>> decorators and "ambient decorators"(from Jonathan's post): >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> 1. decorator that alter the code behavior, the currently >>>>>>>>> proposed decorator. Such as ```@memoize``` >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> 2. decorator that absolutely does not alter the code behavior, >>>>>>>>> only used for optimization, checking or debugging. Instead of @, a distinct >>>>>>>>> syntax will be much clearer ex.```@annotatition@``` (Maybe it >>>>>>>>> should be called annotation instead?): >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> >>>>>>>>> @deprecated@ >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> @number,number=>string@/*type checking*/ >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> @debug("this message will only print in development mode")@ >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> it sounds like terrible idea to have a decorator in code that you >>>>>>>>> can not figure out if it will alter the code behavior by looking at it. I >>>>>>>>> do like to see all the new ideas been added into javascript, but it is also >>>>>>>>> necessary to eliminate the ambiguity whenever possible. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron < >>>>>>>>> jbondc at gdesolutions.com> wrote: >>>>>>>>> >>>>>>>>> On Thu Oct 22 07:44 AM, Andreas Rossberg wrote: >>>>>>>>> > > determined at creation time, allowing for massive engine >>>>>>>>> optimization, >>>>>>>>> > >>>>>>>>> >>>>>>>>> Ya I'm not sure from which hat "massive engine optimization" comes >>>>>>>>> from? >>>>>>>>> >>>>>>>>> What's meant is likely using decorators as annotations (compile >>>>>>>>> time optimizations hints): >>>>>>>>> http://www.google.com/patents/US7013458 >>>>>>>>> <https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.google.com%2fpatents%2fUS7013458&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=atTz2em0YIlXUvUVgiWsZ5xKNjJsIOzm3wLejdDl33E%3d> >>>>>>>>> >>>>>>>>> Or 'ambient decorators': >>>>>>>>> >>>>>>>>> https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators >>>>>>>>> <https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fjonathandturner%2fbrainstorming%2fblob%2fmaster%2fREADME.md%23c6-ambient-decorators&data=01%7c01%7cron.buckton%40microsoft.com%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=1aXPAnWuPpVgE3wCYZqcEnTaksCKqzwuq0bGLkkG8Uo%3d> >>>>>>>>> >>>>>>>>> There's 2 patterns (maybe more?): >>>>>>>>> (a) Tagging a 'tree transformation' on a node. >>>>>>>>> (b) Metadata at compile time on a node. >>>>>>>>> >>>>>>>>> The thing about (b) is it can easily live outside of the code >>>>>>>>> (like in typescript where you have an optional header/declaration file) >>>>>>>>> >>>>>>>>> With (a), it seems more conservative to see how it gets used with >>>>>>>>> classes before bolting on to functions (opinion: end result in java is not >>>>>>>>> something to be proud of). >>>>>>>>> >>>>>>>>> >>>>>>>>> _______________________________________________ >>>>>>>>> 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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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%7c4f28552d1837468197db08d2db08dcea%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=YHeobU0gimD8xIX0FwR3GAdjKwWiwOGNGUWVi%2bHZARg%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/20151023/aae2a8c9/attachment-0001.html>
wycats/javascript-decorators/blob/master/README.md
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