<p dir="ltr">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. </p>
<p dir="ltr">```js<br>
function descriptor(f) {<br>
  return function (target, name, desc) {<br>
    if (arguments.length < 3) return f(target)<br>
    desc.value = f(desc.value)<br>
  }<br>
}</p>
<p dir="ltr">const memoize = descriptor(f => function () {<br>
  // stuff<br>
})</p>
<p dir="ltr">const fibs = memoize(x =><br>
  x < 0 ? 0 :<br>
  x <= 1 ? x :<br>
  fibs(x - 1) + fibs(x - 2))</p>
<p dir="ltr">class Foo {<br>
  @memoize<br>
  method(x) { /* ... */ }<br>
}<br>
```</p>
<p dir="ltr">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). </p>
<p dir="ltr">Python function decorators work similarly, IIRC. </p>
<p dir="ltr">```js<br>
@decorator<br>
function memoize(f) { /* ... */ }</p>
<p dir="ltr">@memoize<br>
function fibs(n) {<br>
  if (x < 0) return 0<br>
  if (x <= 1) return x<br>
  return fibs(x - 1) + fibs(x - 2)<br>
}<br>
```</p>
<br><div class="gmail_quote"><div dir="ltr">On Thu, Oct 22, 2015, 00:34 Jordan Harband <<a href="mailto:ljharb@gmail.com">ljharb@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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*.<div><br></div><div>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() {}`.</div><div><br></div><div>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!</div></div><div dir="ltr"><div><br></div><div>- Jordan</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 21, 2015 at 7:10 PM, Rick Waldron <span dir="ltr"><<a href="mailto:waldron.rick@gmail.com" target="_blank">waldron.rick@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="white-space:pre-wrap">Or just use call constructor:<br><br>class F {<br>  #decorator<br>  call constructor() {<br>    ...<br>  }<br>}<span><font color="#888888"><br>  <br><br>Rick</font></span></div><div><div><br><div class="gmail_quote"><div dir="ltr">On Tue, Oct 20, 2015 at 9:19 AM Matthew Robb <<a href="mailto:matthewwrobb@gmail.com" target="_blank">matthewwrobb@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;color:#444444">Why not just do:<br><br>```<br>const {myFunc} = {<br>  @someDecorator;</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;color:#444444">  myFunc() {<br><br>  }<br>};<br>```</div></div><div class="gmail_extra"></div><div class="gmail_extra"><br clear="all"><div><div><div dir="ltr"><div><br></div>- Matthew Robb</div></div></div></div><div class="gmail_extra">
<br><div class="gmail_quote">On Tue, Oct 20, 2015 at 9:00 AM, Andrea Giammarchi <span dir="ltr"><<a href="mailto:andrea.giammarchi@gmail.com" target="_blank">andrea.giammarchi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">You completely misunderstood me Bob, I don't think there's any valid use case for functions at all, including methods and ... .**specially** methods!!!<div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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!</div><div><br></div><div>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.<br></div><div><br></div><div>Regards</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 20, 2015 at 1:40 PM, Bob Myers <span dir="ltr"><<a href="mailto:rtm@gol.com" target="_blank">rtm@gol.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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?<div><br></div><div>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</div><div><br></div><div>    self_updatify(function a() { })</div><div><br></div><div>but it would be more compact and readable to say</div><div><br></div><div>    @self_updatify</div><div>    function a() { }</div><div><br></div><div>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.)</div><div><br></div><div><div>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).</div><div><br></div><div>The only problem as far as I am aware is how to handle hoisting. </div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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. </div><div><br></div><div>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.</div></div><span><font color="#888888"><div><br></div><div>Bob</div></font></span><span><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 20, 2015 at 4:03 PM, Andrea Giammarchi <span dir="ltr"><<a href="mailto:andrea.giammarchi@gmail.com" target="_blank">andrea.giammarchi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">You haven't provided a single use-case example, like how are you going to decorate a function or why.<div><br></div><div>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.</div><div><br></div><div>One thing I like about current state is that you can use decorators even in ES5 browsers [1]</div><div><br></div><div>Just my 2 cents, Regards</div><div><br></div><div><br></div><div>[1] as shown in the second example of the universal mixin module <a href="https://github.com/WebReflection/universal-mixin#universal-mixin-" target="_blank">https://github.com/WebReflection/universal-mixin#universal-mixin-</a> </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 20, 2015 at 10:30 AM, Axel Rauschmayer <span dir="ltr"><<a href="mailto:rauschma@icloud.com" target="_blank">rauschma@icloud.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><a href="https://github.com/wycats/javascript-decorators/blob/master/README.md" rel="noreferrer" target="_blank">https://github.com/wycats/javascript-decorators/blob/master/README.md</a><br>
<br>
The decorator proposal does not include decorators for functions, because it isn’t clear how to make them work in the face of hoisting.<br>
<br>
However, it would be great to have them. I see two possible solutions:<br>
<br>
– A decorator on a function declaration prevents hoisting.<br>
<br>
– Enable decorators for function expressions, arrow functions and generator function expressions.<br>
<br>
Does either one of those make sense?<br>
<span><font color="#888888"><br>
Axel<span><font color="#888888"><br></font></span></font></span></blockquote></div></div></blockquote></div><br></div></div></span></div>
</blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
<br></blockquote></div><br></div>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
</blockquote></div>
</div></div><br>_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
<br></blockquote></div><br></div>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
</blockquote></div>