> -----Original Message-----
> From: Erik Arvidsson [mailto:[email protected]]
> Sent: Tuesday, April 15, 2014 8:38 AM
> To: [email protected]; [email protected]; Yehuda Katz
> Cc: Ron Buckton
> Subject: Decorators vs Annotations (was April 10 2014 Meeting Notes)
> 
> On Tue Apr 15 2014 at 10:27:23 AM, Rick Waldron <[email protected]
> <mailto:[email protected]> > wrote:
> 
> 
>       ## Decorators for ES7
>       (Yehuda Katz)
> 
>       Slides: (need slides)
> 
>       YK: Presenting aspects of common use cases not yet covered by ES6
> `class`.
> 
>       Knockout.js example (compute the value of a property)
> 
>       WH: Do you want to use functors to produce functions that are per-
> class (i.e. on the prototype) or per-instance?
> 
>       AWB: Per instance wants to be handled in the constructor
> 
>       YUI example (a readonly property)
> 
>       LH/YK: Sometimes you want to say a method is readOnly
> 
>       AWB: No declarative way to describe the per instance state
> 
>       Angular example
> 
>       LH: (explanation) when I declare a class, I also want to register it 
> with
> some other system
> 
>       ES6 Experiments: Angular
> 
>       ```js
>       @NgDirective('[ng-bind]')
>       class NgBind {
>         @Inject([Element])
>         constructor(element) {
>           this.element = element;
>         }
>       }
>       ```
> 
>       AWB: The "@" used to define an annotation
> 
>       JH: Point out that this is inert meta data
> 
> 
> The main use case for Angular is for dependency injection. For that you only
> need meta data.
> 
> Generally decorators are more powerful than annotations since decorators
> can add the meta data as a side effect.
> 
> However, the main issue we ran into with decorators is annotating function
> parameter:
> 
> ```js
> function doSomething(@inject xhr) {
>   ...
> }
> ```
> 
> With decorators it could course be rewritten as:
> ```js
> @annotateParam(inject, 'xhr')
> 
> function doSomething(@inject xhr) {
>   ...
> }
> ```
> 
> Maybe that is sufficient? Maybe that could be done as syntactic sugar?

One options is to use a default instead of a decorator:

```js
function doSomething(xhr = inject('xhr')) {
}
```

Alternatively, a python-like decorator in an argument list position could 
function like this:

```js
// as written:
function doSomething(@inject xhr) {
}

// approximate desugaring:
function doSomething(xhr) {
  xhr = inject(xhr);
}
```

Unfortunately, you lose the ability to use the decorator for pure metadata 
definition and can only use it for mutation during function invocation. 

I experimented with decorators in a fork of TypeScript over a year ago. The 
first run ended up with a very ugly meta type system: 
https://gist.github.com/rbuckton/b2d259d036224a4477f4#metadata-based-param-decorators.

When I was investigating decorators I was looking for a model that worked in 
two ways: 

1. A way to express metadata _about_ something during its definition (akin to 
C# attributes)
2. A way to _mutate/replace_ something during execution

If I wanted to be able to have both the metadata-at-definition and 
mutation-at-execution semantics for argument decorators, I'd need something 
like this:
 
```js
// as written:
function doSometing(@inject xhr) {
}

// approximate desugaring:

// compiler generated identity function
//   using `_doSomething_xhr` here, but in practice this wouldn't be accessible 
as an identifier
var _doSomething_xhr = function(_) { return _; };

function doSomething(xhr) {
  // execute the (possibly mutated/replaced) generated identity function during 
execution of `doSomething`
  xhr = _doSomething_xhr(xhr);
}

// decorate the generated identity function
//   allows for metadata-at-definition semantics
//   `inject` can mutate/replace the identity function which can then affect 
the execution semantics later
_doSomething_xhr = inject(_doSomething_xhr); 
```

The same approach could would for fields in a class (if they are reintroduced 
in ES7):

```js
// as written:
class Sample {
  @inject x;
}

// approximate desugaring:
class Sample {
  constructor() {
    this.x = _Sample_x(this.x);
  }
}
var _Sample_x = function(_) { return _; };
_Sample_x = inject(_Sample_x);
```

Of course, this approach has the obvious downside of allocating a function for 
every argument/field that has a decorator.

Ron
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to