Proposal: user defined attributes

Adam D. Ruppe destructionator at gmail.com
Fri Mar 16 06:35:54 PDT 2012


On the ride over here today, I had a thought that
I think neatly solves the user defined attribute
question.

enum Serializable { yes, no }

@note(Serializable.yes) int a;


We introduce two new things to the language:

1) the @note(expression) attribute. You can put
as many "notes" on a declaration as you want by
simply listing them.

The expression inside is appended to a list on
the declaration.

This would be valid on variables, functions,
function parameters, struct members, etc.

2) __traits(getNotes, decl). This returns a tuple
of all the note expressions.

foreach(i, exp; __traits(getNotes, a)) {
    static assert(is(typeof(exp) == Serializable);
    static assert(exp == Serializable.yes);
}




This simple extension to the language enables libraries,
using existing traits to navigate symbols, to get
additional information about things and implement it
however.

The lack of user defined attributes is D's biggest missed
opportunity right now, and I think this simple proposal
will plug that hole.



Previous user-defined attribute proposals have had counter
arguments like these:

1) how do you define what is and is not a valid attribute?

Here, the answer is pretty simple: you can put whatever notes
you want on the thing. Whether the library uses it or not
is up to it.

It has to be a valid type - so the compiler will catch
typos and whatnot - but it doesn't have to be used unless
you ask for it.


2) OK, how do you namespace things so different libraries don't
get different results?

That's where the beauty of the expression type comes in: D
already has namespaces. foo.Serializable != bar.Serializable,
so there's no conflict.

We simply declare types. The enum X {yes, no} pattern is already
common in Phobos, and is also the best way to express a bool 
condition
here. (Technically, @note(true) would compile, but it'd be much 
less
useful than declaring a name for the note too, with an enum.)

Name conflicts is a problem already solved by the language.


3) Can we have shared attributes, with declared names so people
know what to use in their own libraries?

Yes, we could add some to std.traits or make a new std.notes that
declare some common items as enums.

Though, I think having the types declared in the modules that use
them is generally more useful.


But, again, the library problem is already solved, and we're
just using that!





I think this is a winner... and I think I can do it in the
compiler in less time than it will take to convince git to
give me a clean pull request.


Am I missing anything?


More information about the Digitalmars-d mailing list