custom attribute proposal (yeah, another one)

Piotr Szturmaj bncrbme at jadamspam.pl
Fri Apr 6 12:03:39 PDT 2012


Steven Schveighoffer wrote:
> On Fri, 06 Apr 2012 10:56:19 -0400, Piotr Szturmaj
> <bncrbme at jadamspam.pl> wrote:
>
>> Steven Schveighoffer wrote:
>>> You can store a struct, just return it from an attribute function.
>>>
>>> e.g.:
>>>
>>> @attribute Author author(string name) { return Author(name);}
>>
>> Compare it to:
>>
>> struct Author { string name; }
>>
>> @Author("John Doe") int x;
>
> so now I must define a type for every attribute? I'd rather just define
> a function.

So declaration is always needed, no matter what attribute is.

> What if I have 20 string attributes, I must define a new attribute type
> for each one? This seems like unneeded bloat.

I don't see advantage of functions here, twenty of them is also a bloat. 
Different types give you different _names_ for different purposes. Those 
_names_ are crucial to support the attributes.

How do you get list of all attributes with your function based proposal? 
You can get a string attribute but you don't know which function 
generated it. You don't know if it was serializable, author or whatever.

> BTW, if I wasn't trying to demonstrate that you could store structs, I
> would have written:
>
> @attrubte string author(string name) { return name;}
>
> and save the extra bloat associated with declaring another type. Maybe
> we could even get this someday:

As above, declaring another function is also a bloat.

> @attribute author(string name) => name;
>
> I just don't see the need to declare a type that can wrap a string.
>
> You could even add this rule:
>
> if @attribute is placed on a struct, its constructor becomes an
> @attribute qualified function with the name of the struct as the
> attribute name.

Consider struct constructors as equivalent of functions proposed by you. 
Here you declare a type, there you declare a function. They're very 
similar, besides that struct type _describes_ the attribute. A function 
on the other side just returns a value, which doesn't have any name 
attached to it.

>>> Why should we be restricted to only structs? Or any type for that
>>> matter?
>>
>> When using __traits(getAttributes, ...) you ask for conrete (struct)
>> type and you get it. In case of function you ask for serializable but
>> you get a bool.
>
> It's an example. you can choose any type you want! I actually just want
> the name of the author, I don't care whether that's a struct, or a string.

Yes, but my point is that you get a bool and you don't know which of the 
functions returned it, as many of them can return bool.

>>> The benefit to using CTFE functions is that the compiler already knows
>>> how to deal with them at compile-time. i.e. less work to make the
>>> compiler implement this.
>>
>> Compiler can easily deal with structs too:
>
> I concede this is probably a non-issue.
>
>>> I also firmly believe that determining what is allowed as attributes
>>> should be opt-in. Just allowing any struct/class/function/etc. would
>>> lead to bizarre declarations.
>>
>> C# has requirement that attributes are classes that derive from base
>> Attribute class. But without that limitation you can do things like:
>>
>> @Uuid("...")
>> interface MyIntf { }
>>
>> without explicitly declaring Uuid as attribute. However, I don't see
>> any usage for primitive types:
>>
>> @5
>> @"s"
>> @false
>
> I don't understand what you are saying here.

"Just allowing any struct/class/function/etc. would
lead to bizarre declarations."

Allowing _any_ type would indeed lead to bizarre declarations, but I 
think that allowing any struct or class may be useful.

Alternatively structs or classes may require some additional member. 
This will allow only selected types to work as attributes.

>> I think that allowing values of structs, classes and _eventually_
>> enums should be enough.
>
> Any CTFE computed value should suffice.

I think that list of attributes should be a list of user defined types. 
You can always write a function to construct them, but anyway you get 
named user defined type (like struct). Named type easily disambiguates 
between different attributes without resorting to name-value solutions.

This is how it's done in C# by the way.


More information about the Digitalmars-d mailing list