Le 06/04/2012 15:23, Steven Schveighoffer a écrit :
OK, so I woke up this morning to find a huge discussion on attributes,
and I'd like to once again propose the idea of how to define and use an
attribute.

I do not like the idea of:

@attr(identifier)

Why? Because what the hell did we create that "@" syntax for? I though
it was to avoid misinterpreting such things as normal symbols, and avoid
creating new keywords. Why should the compiler be the only one able to
use such symbols?

Another thing I don't like is some idea that only a certain type of
construct can be the identifier. An attribute should have one
requirement -- that it can be created/determined at compile time.

So here is my proposal:

1. Introduce a new compiler-defined attribute @attribute (or @attr or
something better, the name isn't important).
2. This attribute can *only* be used on a module-level function.
3. @attribute functions *must* be CTFE-able.
4. An @attribute function can be used as a user-defined attribute on any
declaration using the syntax @identifier where identifier is the name of
the attribute function (subject to normal function lookup rules). If the
attribute can be called without parameters, the parentheses are optional.
5. When used on a declaration, that CTFE function is called during
compile-time, and the result of that function is stored as metadata on
that symbol. It does not affect the type of the symbol or transfer to
any other symbols that are assigned to the value of that declaration (in
other words, it *cannot* be used as a type constructor).
6. The metadata is stored in a key-value pair, with the key being the
symbol of the @attribute function, and the value being the result of the
CTFE function.
7. One can lookup whether an attribute exists on a symbol using
__traits(hasAttribute, symbol).
8. One can retrieve the value of the CTFE result using
__traits(getAttribute, symbol). If the CTFE function returns void, this
is a compiler error.

And that's it. We can extend this eventually to storing something in
TypeInfo, but I'm not sure we need that. However, I want to stress that
having runtime type metadata is not a requirement for this proposal.

Example usage:

@attribute bool serializable(bool yesorno = true) { return yesorno; }

unittest {
// serializable is a normal function also
assert(serializable() == true);
assert(serializable(true) == true);
assert(serializable(false) == false);
}

@serializable struct MyType
{
int x;
int y;
@serializable(false) int z;
}

string serialize(T)(const ref T t) if (__traits(hasAttribute,
serializable) && __traits(getAttribute, serializable))
{
// serialize each field. Skip any fields that are marked as serializable
== false
}

-Steve

The struct proposal from previous thread was superior because it provide similar capability without as much language change.

Reply via email to