April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tove | On Fri, 06 Apr 2012 13:33:33 -0400, Tove <tove@fransson.se> wrote:
> I think this proposal pretty much covers what I would expect from 'custom attributes'... but what about adding a D twist, getting "what we annotate" as a template parameter so that one among other things can make use of Template Constraints?
Interesting, so something like:
@attribute string defaultName(T)() if(is(typeof(T.init.name))) { return T.init.name;}
Not sure how much this gives us, but it definitely feels doable.
-Steve
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On 04/06/2012 07:04 AM, Manu wrote:
> I think Johannes proposal already nails it. What benefits would be
> merged from this proposal? How would they influence the design?
>
> On 04/06/2012 11:41 AM, Johannes Pfau wrote:
>
> Declaring a custom attribute:
> ---------
> module std.something;
>
> struct Author
> {
> string name;
> public this(string name)
> {
> this.name <http://this.name> = name;
> }
> }
> ---------
Why not being more flexible .. Likewise
struct Annotation //Throw in all your annotations
{
Variant[] [string] map;
Variant[] opDispatch(string key)()
{
return map[key];
}
// Single value
Variant[] opDispatch(string key, T) (T t )
if ( !isArray!T && !isTuple!T )
{
index ~= key;
map[key] ~= to!Variant(t);
return map[key];
}
....Array, Tuple
}
well.. I am not sure about CTFE
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to bls | On 04/06/2012 10:51 AM, bls wrote:
> On 04/06/2012 07:04 AM, Manu wrote:
>> I think Johannes proposal already nails it. What benefits would be
>> merged from this proposal? How would they influence the design?
>>
>> On 04/06/2012 11:41 AM, Johannes Pfau wrote:
>>
>> Declaring a custom attribute:
>> ---------
>> module std.something;
>>
>> struct Author
>> {
>> string name;
>> public this(string name)
>> {
>> this.name <http://this.name> = name;
>> }
>> }
>> ---------
>
Oh the joy of copy and paste ..
struct Annotation //Throw in all your annotations
{
Variant[] [string] map;
Variant[] opDispatch(string key)()
{
return map[key];
}
// Single value
void opDispatch(string key, T) (T t )
if ( !isArray!T && !isTuple!T )
{
map[key] ~= to!Variant(t);
return;
}
// Allow ....Array and Tuple too
}
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 6 April 2012 at 17:44:25 UTC, Steven Schveighoffer wrote:
> On Fri, 06 Apr 2012 13:33:33 -0400, Tove <tove@fransson.se> wrote:
>> I think this proposal pretty much covers what I would expect from 'custom attributes'... but what about adding a D twist, getting "what we annotate" as a template parameter so that one among other things can make use of Template Constraints?
>
> Interesting, so something like:
>
> @attribute string defaultName(T)() if(is(typeof(T.init.name))) { return T.init.name;}
>
> Not sure how much this gives us, but it definitely feels doable.
>
> -Steve
yes, exactly... well, once library designers start getting creative, one of the immediate benefits would be, easy to understand error-messages.
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | Am 06.04.2012 17:17, schrieb Adam D. Ruppe:
> On Friday, 6 April 2012 at 15:07:04 UTC, Manu wrote:
>> But maybe the function approach has an
>> effect on the simplicity of the expression for a simple attribute,
>> like a single bool?
>
> Meh, it is pretty similar:
>
> struct Serializable { bool yes; }
> bool Serializable(bool yes) { return yes; }
>
There's one difference I think.
struct approach:
struct Area { int x, y; }
Area sqare(int a) { return Area(x, y); }
//foo and bar are attributed the same
@Area(5, 5) int foo();
@square(5) int bar();
whereas with the function approach:
@area(5, 5) int foo();
@square(5) int bar();
foo and bar have different attributes.
The problem is you can't define forwarding functions because the symbol is the attribute type. This seems to be a major problem to me.
Mafi
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mafi | On Fri, 06 Apr 2012 14:23:45 -0400, Mafi <mafi@example.org> wrote:
> Am 06.04.2012 17:17, schrieb Adam D. Ruppe:
>> On Friday, 6 April 2012 at 15:07:04 UTC, Manu wrote:
>>> But maybe the function approach has an
>>> effect on the simplicity of the expression for a simple attribute,
>>> like a single bool?
>>
>> Meh, it is pretty similar:
>>
>> struct Serializable { bool yes; }
>> bool Serializable(bool yes) { return yes; }
>>
>
> There's one difference I think.
> struct approach:
> struct Area { int x, y; }
> Area sqare(int a) { return Area(x, y); }
> //foo and bar are attributed the same
> @Area(5, 5) int foo();
> @square(5) int bar();
>
> whereas with the function approach:
> @area(5, 5) int foo();
> @square(5) int bar();
> foo and bar have different attributes.
>
> The problem is you can't define forwarding functions because the symbol is the attribute type. This seems to be a major problem to me.
I acknowledge this limitation. But we can also overload functions:
@attribute Area area(int w, int h) { return Area(w, h);}
@attribute Area area(int w) { return Area(w, w);}
Granted, area is not as obvious as square (it's actually a bad name, it should be something like dimensions), but being able to have more than one attribute of the same type I think is essential.
Also, if I see:
@square(5) int foo();
How do I know that I have to use __traits(getAttribute, foo, Area)?
Another possibility:
@attribute Area area(int w, int h) { return Area(w, h);}
@attribute Area area(Area a) { return a;}
Area square(int a) { return Area(a, a);}
@area(5, 5) int foo();
@area(square(5)) int bar();
-Steve
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer wrote: > On Fri, 06 Apr 2012 10:56:19 -0400, Piotr Szturmaj > <bncrbme@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. |
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer wrote: > On Fri, 06 Apr 2012 13:33:33 -0400, Tove <tove@fransson.se> wrote: >> I think this proposal pretty much covers what I would expect from >> 'custom attributes'... but what about adding a D twist, getting "what >> we annotate" as a template parameter so that one among other things >> can make use of Template Constraints? > > Interesting, so something like: > > @attribute string defaultName(T)() if(is(typeof(T.init.name))) { return > T.init.name;} > > Not sure how much this gives us, but it definitely feels doable. See also: http://forum.dlang.org/post/jlmtcv$v09$1@digitalmars.com |
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 4/6/12 6:23 AM, Steven Schveighoffer wrote:
> 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.
There may be a good reason why it's not supported, but in Java I've often wished I could repeat an annotation with different values. 'Twould be fantastic if D allowed this.
|
April 06, 2012 Re: custom attribute proposal (yeah, another one) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Piotr Szturmaj | On Fri, 06 Apr 2012 15:03:39 -0400, Piotr Szturmaj <bncrbme@jadamspam.pl> wrote: > Steven Schveighoffer wrote: >> 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. Unused function do not make it into the EXE. > 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. foreach(name, value; __traits(getAttributes, symbol)) {...} hereby added to the proposal. > >> 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. No, it doesn't generate more typeinfo that must go into the EXE. When the EXE is built, all associated bloat should disappear, it's only needed during compilation. >> @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. The name is the function. You seem to be arguing the equivalent of: "int x is useless. It should really just be int. If you need another integer field, make a new type that's just like int, how hard is that?" Yeah, I know it's a strawman, but this is seriously how it sounds to me ;) >> 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. I think you are missing how the metadata is stored as key-value pairs, with the key being the name of the function that was used. >> 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. Again, see point above about not naming variables. > This is how it's done in C# by the way. Yes I know. I don't think we need to limit ourselves this way, C# does not have the compile-time power that D does. -Steve |
Copyright © 1999-2021 by the D Language Foundation