Custom attributes (again)

Walter Bright newshound2 at digitalmars.com
Fri Apr 6 03:12:52 PDT 2012


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.


> 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.

> 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.


More information about the Digitalmars-d mailing list