On 4/6/12 6:12 PM, Walter Bright wrote:
On 4/6/2012 2:50 AM, Ary Manzana wrote:
The syntax in Java for declaring an attribute:
public @interface Foo {
String xxx;
int yyy;
}
In D maybe @interface could be used to (in order to avoid introducing
another
keyword... or maybe use @attribute instead):
@attribute Foo {
string xxx;
int yyy;
}
I don't see the need for creating a new kind of symbol.
2. You use them by using their names. What you are proposing if for
attribute
foo to be @attr(foo). But in Java it's @foo.
So in Java you would use that attribute like this:
@Foo(xxx = "hello", yyy = 1);
void func() {}
Then you can get the "Foo" attribute in func, and ask for it's xxx and
yyy.
This is a runtime system.
Yes, but I'm thinking about a compile-time system (as I showed in the
example usages below).
Now, your proposal is much simpler and it will become inconvenient in
some
cases. For example suppose you want to provide attributes for
serialization (I
guess the classic example). With your proposal it would be:
/// This is actually an attribute. Use this together with
serialized_name.
enum serialize = 1;
enum serialized_name = 2;
@attr(serialize = true, serialized_name = "Foo")
int x;
No, it would be:
enum serialize = true;
enum serialize_name = "Foo";
@attr(serialize, serialized_name) int x;
There would be no initialization in the @attr syntax.
Hmmm... I didn't get that quite well. You are using the symbol's name as
the attribute name? In my example I missed splitting it into two files:
my_attributes.d:
@attribute serialize { }
my_usage_of_it.d:
import my_attributes;
@serialize(...)
Now, with the way things are done in Java and C#:
/// Marks a field to be serialized.
@attribute serialize {
/// The name to be used.
/// If not specified, the name of the member will be used instead.
string name;
}
@serialize(name = "Foo")
int x;
You can see the syntax is much cleaner. The attribute declaration also
serves as
documentation and to group attributes related to the serialization
process.
I don't see that it is cleaner - there's no particular reason why a new
symbol type needs to be introduced.
Now, to implement this is not very much difficult than what you proposed.
1. Introduce the syntax to define attributes. Piece of cake, since
it's much
more or less the syntax of a struct, but functions or nested types are
not
allowed. Parse them into an AttributeDecl or something like that.
2. When the compiler finds @attr(field = value) it uses normal lookup
rules to
find "attr". Then it checks it's an attributes. Then all fields are
check in
turn to see if their type match. You can probably put there anything
that's
compile-time evaluatable, though usually primitive types and strings
are enough.
If a field is not specified, it's type.init will be used.
3. The syntax for querying is almost the same as you proposed:
__traits(hasAttribute, x, serializable) // true
__traits(getAttribtue, x, serializable, name) // "Foo"
4. Declare the core attributes in object.di or similar: @safe,
@nothrow, etc.
You can also document them.
5. Probably deprecate __traits(isSafe) and so on, since hasAttribute
can be used
for that.
@safe, @nothrow, etc., require a lot of semantic support in the
compiler. They cannot pretend to be user defined attributes.
Yes they can. That's how it is done in C# and Java. In fact, IUnknown is
pretending to be an interface and has semantic support in the compiler.