Decorators vs Annotations (was April 10 2014 Meeting Notes)
One options is to use a default instead of a decorator:
function doSomething(xhr = inject('xhr')) {
}
Alternatively, a python-like decorator in an argument list position could function like this:
// 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: 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:
- A way to express metadata about something during its definition (akin to C# attributes)
- 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:
// 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):
// 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.
On Tue Apr 15 2014 at 10:27:23 AM, Rick Waldron <waldron.rick at gmail.com>
wrote:
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:
function doSomething(@inject xhr) { ... }
With decorators it could course be rewritten as:
@annotateParam(inject, 'xhr') function doSomething(@inject xhr) { ... }
Maybe that is sufficient? Maybe that could be done as syntactic sugar?