Decorators for functions
Salvador de la Puente González
salva at unoyunodiez.com
Fri Oct 23 09:56:28 UTC 2015
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>
More information about the es-discuss
mailing list