User Defined Attributes
References: http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html Inspired by a gallon of coffee, I decided to get it implemented. It's simple, based on what D already does (CTFE and heterogeneous tuples), easy to implement, easy to understand, and doesn't break anything. It should do everything asked for in the above references (except it's not a type constructor). You can download it here and try it out: http://ftp.digitalmars.com/dmd2beta.zip As a bonus, that beta also can generate Win64 executables, and you can even symbolically debug them with VS! (Thanks to Rainer Schütze for his invaluable help with that). Here's the rather skimpy and lame spec I banged out: = User Defined Attributes --- User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them. Grammatically, a UDA is a StorageClass: StorageClass: UserDefinedAttribute UserDefinedAttribute: [ ArgumentList ] And looks like: [ 3 ] int a; [ string, 7 ]: int b; If there are multiple UDAs in scope for a declaration, they are concatenated: [ 1 ] { [ 2 ] int a;// has UDA's [1,2] [ string ] int b; // has UDA's [1,string] } UDA's can be extracted into an expression tuple using __traits: [ 'c' ] string s; pragma(msg, __traits(getAttributes, s)); prints: tuple('c') If there are no user defined attributes for the symbol, an empty tuple is returned. The expression tuple can be turned into a manipulatable tuple: template Tuple(T...) { alias T Tuple; } enum EEE = 7; [hello] struct SSS { } [3] { [4][EEE][SSS] int foo; } alias Tuple!(__traits(getAttributes, foo)) TP; pragma(msg, TP); pragma(msg, TP[2]); prints: tuple(3,4,7,(SSS)) 7 and of course the tuple types can be used to declare things: TP[3] a;// a is declared as an SSS The attribute of the type name is not the same as the attribute of the variable: pragma(msg, __traits(getAttributes, typeof(a)); prints: tuple(hello) Of course, the real value of UDA's is to be able to create user defined types with specific values. Having attribute values of basic types does not scale. The attribute tuples can be manipulated like any other tuple, and can be passed as the argument list to a template. Whether the attributes are values or types is up to the user, and whether later attributes accumulate or override earlier ones is also up to how the user interprets them.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: References: http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html Inspired by a gallon of coffee, I decided to get it implemented. It's simple, based on what D already does (CTFE [*drool*, totally perfect awesomeness] Thanks!
Re: User Defined Attributes
Wow, that's a surprise! Just yesterday I was thinking that it would be really nice to have them for a piece of code ;) But shouldn't we keep the syntax closer to normal attributes and other languages(*)? I see a lot of arguments for doing that, with the only counter-argument that they would be in the same namespace as the built-in attributes (which should not be that bad, as this is very low level language stuff). (*) i.e. @mytype or @(string) and without the '[]'
Re: User Defined Attributes
On 11/6/2012 12:15 AM, Tove wrote: [*drool*, totally perfect awesomeness] Thanks! The neato thing is I realized I could just connect the dots on what D already does well - CTFE, tuples, and templates. The actual features can now be added by library routines.
Re: User Defined Attributes
On 11/6/2012 12:20 AM, Sönke Ludwig wrote: But shouldn't we keep the syntax closer to normal attributes and other languages(*)? I see a lot of arguments for doing that, with the only counter-argument that they would be in the same namespace as the built-in attributes (which should not be that bad, as this is very low level language stuff). (*) i.e. @mytype or @(string) and without the '[]' We can debate the syntax. I don't have a store set by this one. I was more interested in getting the semantics right. Anyhow, it's nice to have a working prototype to experiment with rather than a paper airplane.
Re: User Defined Attributes
On 11/6/2012 12:39 AM, Jakob Ovrum wrote: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: -snip- It doesn't look like it would be possible to schedule any runtime code using this, meaning they're not usable for stuff like registering types for serialization support, or doing runtime linking when attached to a function pointer, etc. Since D allows one to inquire and get a list of symbols, one can then iterate over them at compile time to determine which are serializable (or have some other specific attribute).
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:42:44 UTC, Walter Bright wrote: Since D allows one to inquire and get a list of symbols, one can then iterate over them at compile time to determine which are serializable (or have some other specific attribute). Yes, but somewhere you have to put startup code pointing in the general direction of where the attributes are used (like a module), it's not automatic. A static constructor cannot be used because it has no idea where to look. But, I yield until someone comes up with actual examples of how these UDAs are useful, because I can't think of anything interesting at the moment. I guess I should go read over the old discussions you linked (I remember participating, but can't remember any specifics).
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: snip Nice to hear because it was unexpected and was requested prevously by community.
Re: User Defined Attributes
On 11/6/2012 12:42 AM, Walter Bright wrote: Since D allows one to inquire and get a list of symbols, one can then iterate over them at compile time to determine which are serializable (or have some other specific attribute). To emphasize, the User Defined Attributes thing is completely a compile time feature. However, a user defined runtime system can be built on top of it. It gives the best of both worlds.
Re: User Defined Attributes
Am 06.11.2012 09:26, schrieb Walter Bright: On 11/6/2012 12:20 AM, Sönke Ludwig wrote: But shouldn't we keep the syntax closer to normal attributes and other languages(*)? I see a lot of arguments for doing that, with the only counter-argument that they would be in the same namespace as the built-in attributes (which should not be that bad, as this is very low level language stuff). (*) i.e. @mytype or @(string) and without the '[]' We can debate the syntax. I don't have a store set by this one. I was more interested in getting the semantics right. Anyhow, it's nice to have a working prototype to experiment with rather than a paper airplane. Definitely! Thanks a lot for tackling this, to me this seems like something that can get a real killer feature for the language!
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:39:47 UTC, Jakob Ovrum wrote: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: -snip- It doesn't look like it would be possible to schedule any runtime code using this, meaning they're not usable for stuff like registering types for serialization support, or doing runtime linking when attached to a function pointer, etc. Runtime arrtibutes can be implemented as properties in object.d. This would work for classes only and for other types it can be implemented manually. Runtime attributes require substantial amount of work, introducing bugs, bloating ABI and new questions about how this feature does work with others.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:50:32 UTC, Walter Bright wrote: To emphasize, the User Defined Attributes thing is completely a compile time feature. However, a user defined runtime system can be built on top of it. It gives the best of both worlds. Problem is that there's no way to do this without having the user specify which modules it should work for, like: import attributes; import a, b, c; static this() // This code cannot be automated. { initAttributes!a(); initAttributes!b(); initAttributes!c(); }
Re: User Defined Attributes
Am 06.11.2012 09:49, schrieb Jakob Ovrum: But, I yield until someone comes up with actual examples of how these UDAs are useful, because I can't think of anything interesting at the moment. I guess I should go read over the old discussions you linked (I remember participating, but can't remember any specifics). you're just to deep catched in the .Net-Everything-Is-Done-In-Runtime-Paradigm - thats all :) most of the stuff .Net does in runtime is not absolutely needed at runtime - but they need to because there is no compiletime reflection system available at all - and that trains developer to always thing in runtime-aspects - always
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:56:26 UTC, Maxim Fomin wrote: Runtime arrtibutes can be implemented as properties in object.d. This would work for classes only and for other types it can be implemented manually. Runtime attributes require substantial amount of work, introducing bugs, bloating ABI and new questions about how this feature does work with others. I'm not suggesting runtime attributes should be part of the language, nor am I suggesting we add them to Phobos. All I'm saying is the UDA system has to be powerful enough that it *could* be implemented in a library if desired.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:55:06 UTC, Sönke Ludwig wrote: Am 06.11.2012 09:26, schrieb Walter Bright: On 11/6/2012 12:20 AM, Sönke Ludwig wrote: But shouldn't we keep the syntax closer to normal attributes and other languages(*)? I see a lot of arguments for doing that, with the only counter-argument that they would be in the same namespace as the built-in attributes (which should not be that bad, as this is very low level language stuff). (*) i.e. @mytype or @(string) and without the '[]' We can debate the syntax. I don't have a store set by this one. I was more interested in getting the semantics right. Anyhow, it's nice to have a working prototype to experiment with rather than a paper airplane. Definitely! Thanks a lot for tackling this, to me this seems like something that can get a real killer feature for the language! @test void myUnittest() { } Uh yeah, that would be awesome!
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 09:03:49 UTC, dennis luehring wrote: you're just to deep catched in the .Net-Everything-Is-Done-In-Runtime-Paradigm - thats all :) No.
Re: User Defined Attributes
n 11/6/2012 12:59 AM, Jakob Ovrum wrote: Problem is that there's no way to do this without having the user specify which modules it should work for, like: import attributes; import a, b, c; static this() // This code cannot be automated. { initAttributes!a(); initAttributes!b(); initAttributes!c(); } Is that really a problem?
Re: User Defined Attributes
On 11/6/2012 12:49 AM, Maxim Fomin wrote: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: snip Nice to hear because it was unexpected and was requested prevously by community. I've been intending to do it for a while now.
Re: User Defined Attributes
Am 06.11.2012 10:04, schrieb Jakob Ovrum: On Tuesday, 6 November 2012 at 09:03:49 UTC, dennis luehring wrote: you're just to deep catched in the .Net-Everything-Is-Done-In-Runtime-Paradigm - thats all :) No. ok not you - but many others
Re: User Defined Attributes
On 11/6/2012 1:06 AM, Jonas Drewsen wrote: Wow! This is an early christmas gift. Just to be sure. Is the following also possible: [Serializable] class Foo { int bar; } This will attach the UDA to the ClassDeclaration. The examples you've shown only attach UDAs to variable declarations. /Jonas Yes, you can attach them to other symbols, including user defined types.
Re: User Defined Attributes
Wow! This is an early christmas gift. Just to be sure. Is the following also possible: [Serializable] class Foo { int bar; } This will attach the UDA to the ClassDeclaration. The examples you've shown only attach UDAs to variable declarations. /Jonas
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 09:08:25 UTC, Walter Bright wrote: On 11/6/2012 1:06 AM, Jonas Drewsen wrote: Wow! This is an early christmas gift. Just to be sure. Is the following also possible: [Serializable] class Foo { int bar; } This will attach the UDA to the ClassDeclaration. The examples you've shown only attach UDAs to variable declarations. /Jonas Yes, you can attach them to other symbols, including user defined types. Great. Can't wait to play around with this. I think project Orange could really take advantage of this. /Jonas
Re: User Defined Attributes
Walter Bright wrote: References: http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html Inspired by a gallon of coffee, I decided to get it implemented. It's simple, based on what D already does (CTFE and heterogeneous tuples), easy to implement, easy to understand, and doesn't break anything. It should do everything asked for in the above references (except it's not a type constructor). You can download it here and try it out: http://ftp.digitalmars.com/dmd2beta.zip As a bonus, that beta also can generate Win64 executables, and you can even symbolically debug them with VS! (Thanks to Rainer Schütze for his invaluable help with that). Here's the rather skimpy and lame spec I banged out: = User Defined Attributes --- User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them. Grammatically, a UDA is a StorageClass: StorageClass: UserDefinedAttribute UserDefinedAttribute: [ ArgumentList ] And looks like: [ 3 ] int a; [ string, 7 ]: int b; If there are multiple UDAs in scope for a declaration, they are concatenated: [ 1 ] { [ 2 ] int a;// has UDA's [1,2] [ string ] int b; // has UDA's [1,string] } UDA's can be extracted into an expression tuple using __traits: [ 'c' ] string s; pragma(msg, __traits(getAttributes, s)); prints: tuple('c') If there are no user defined attributes for the symbol, an empty tuple is returned. The expression tuple can be turned into a manipulatable tuple: template Tuple(T...) { alias T Tuple; } enum EEE = 7; [hello] struct SSS { } [3] { [4][EEE][SSS] int foo; } alias Tuple!(__traits(getAttributes, foo)) TP; pragma(msg, TP); pragma(msg, TP[2]); prints: tuple(3,4,7,(SSS)) 7 and of course the tuple types can be used to declare things: TP[3] a;// a is declared as an SSS The attribute of the type name is not the same as the attribute of the variable: pragma(msg, __traits(getAttributes, typeof(a)); prints: tuple(hello) Of course, the real value of UDA's is to be able to create user defined types with specific values. Having attribute values of basic types does not scale. The attribute tuples can be manipulated like any other tuple, and can be passed as the argument list to a template. Whether the attributes are values or types is up to the user, and whether later attributes accumulate or override earlier ones is also up to how the user interprets them. I wonder what are the benefits over a library solution. Something like struct UserDefinedAttribute(Args...) { alias Args[0 .. $ -1] attributes; } unittest { UserDefinedAttribute!(my attr, int) a; UserDefinedAttribute!(my attr, 4, int) b; import std.stdio; writeln(typeof(a).attributes.stringof); writeln(typeof(b).attributes.stringof); } which admittedly has less syntactical appeal (and probably other problems) but can maybe improved. But to which point. What do you gain by adding it to the core language? Jens
Re: User Defined Attributes
Am 06.11.2012 09:39, schrieb Jakob Ovrum: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: -snip- It doesn't look like it would be possible to schedule any runtime code using this, meaning they're not usable for stuff like registering types for serialization support, or doing runtime linking when attached to a function pointer, etc. Even with user defined types or functions used in the attribute, the type or function itself doesn't know anything about the symbol it is being attached to, so it's quite limited what it can do. Compared to other prevalent UDA systems, like C#'s, I'd say that this one is extremely limiting due to the two above points. I'd love to hear some examples of what this particular take on UDAs allows in D, though. I see this as a feature in a way. The way C# attributes are sometimes used can feel a lot like magic, because they can do things on their own. In contrast it feels quite clean to me to simply think of attributes of what the word means - a simple tag on the declaration. Some otherwise possible globally operating applications may not be doable without some boilerplate code. But a lot of stuff, including controlling seralization, interface generation or statically checked custom type constraints should be perfectly possible.
Re: User Defined Attributes
Jens Mueller wrote: Walter Bright wrote: References: http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html Inspired by a gallon of coffee, I decided to get it implemented. It's simple, based on what D already does (CTFE and heterogeneous tuples), easy to implement, easy to understand, and doesn't break anything. It should do everything asked for in the above references (except it's not a type constructor). You can download it here and try it out: http://ftp.digitalmars.com/dmd2beta.zip As a bonus, that beta also can generate Win64 executables, and you can even symbolically debug them with VS! (Thanks to Rainer Schütze for his invaluable help with that). Here's the rather skimpy and lame spec I banged out: = User Defined Attributes --- User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them. Grammatically, a UDA is a StorageClass: StorageClass: UserDefinedAttribute UserDefinedAttribute: [ ArgumentList ] And looks like: [ 3 ] int a; [ string, 7 ]: int b; If there are multiple UDAs in scope for a declaration, they are concatenated: [ 1 ] { [ 2 ] int a;// has UDA's [1,2] [ string ] int b; // has UDA's [1,string] } UDA's can be extracted into an expression tuple using __traits: [ 'c' ] string s; pragma(msg, __traits(getAttributes, s)); prints: tuple('c') If there are no user defined attributes for the symbol, an empty tuple is returned. The expression tuple can be turned into a manipulatable tuple: template Tuple(T...) { alias T Tuple; } enum EEE = 7; [hello] struct SSS { } [3] { [4][EEE][SSS] int foo; } alias Tuple!(__traits(getAttributes, foo)) TP; pragma(msg, TP); pragma(msg, TP[2]); prints: tuple(3,4,7,(SSS)) 7 and of course the tuple types can be used to declare things: TP[3] a;// a is declared as an SSS The attribute of the type name is not the same as the attribute of the variable: pragma(msg, __traits(getAttributes, typeof(a)); prints: tuple(hello) Of course, the real value of UDA's is to be able to create user defined types with specific values. Having attribute values of basic types does not scale. The attribute tuples can be manipulated like any other tuple, and can be passed as the argument list to a template. Whether the attributes are values or types is up to the user, and whether later attributes accumulate or override earlier ones is also up to how the user interprets them. I wonder what are the benefits over a library solution. Something like struct UserDefinedAttribute(Args...) { alias Args[0 .. $ -1] attributes; } unittest { UserDefinedAttribute!(my attr, int) a; UserDefinedAttribute!(my attr, 4, int) b; import std.stdio; writeln(typeof(a).attributes.stringof); writeln(typeof(b).attributes.stringof); } which admittedly has less syntactical appeal (and probably other problems) but can maybe improved. But to which point. What do you gain by adding it to the core language? No need to reply. Since you said already Yes, you can attach them to other symbols, including user defined types. That wasn't obvious from the examples. That's why it looked initially limited to me. Jens
Re: User Defined Attributes
Tooo much fun! Argh, _must_ _stop_ _playing_ and actually work ;( [int a;] class A { } class B : A { mixin(__traits(getAttributes, typeof(super))[0]); } can't wait to see all the creative uses this will enable!
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 10:10:37 UTC, Tove wrote: Tooo much fun! Argh, _must_ _stop_ _playing_ and actually work ;( [int a;] class A { } class B : A { mixin(__traits(getAttributes, typeof(super))[0]); } can't wait to see all the creative uses this will enable! Or obfuscation :)
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 09:24:58 UTC, Jens Mueller wrote: which admittedly has less syntactical appeal (and probably other problems) but can maybe improved. But to which point. What do you gain by adding it to the core language? Jens In the initial discussions, I was hoping that the symbol itself would be made available in some fashion. For example, enabling something like this: template Test(alias sym) { pragma(msg, test attribute was attached to:); pragma(msg, sym); enum Test = true; } [Test] int a; However, I can imagine that it's always possible to work around this by doing the actual work later when both the symbol and attribute are available.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 09:07:34 UTC, Walter Bright wrote: Is that really a problem? I don't strictly need it for any of my projects, where I'm already using lazy initialization for these cases. I guess time will tell if it's significant for other applications.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:20:42 UTC, Walter Bright wrote: On 11/6/2012 12:15 AM, Tove wrote: [*drool*, totally perfect awesomeness] Thanks! The neato thing is I realized I could just connect the dots on what D already does well - CTFE, tuples, and templates. The actual features can now be added by library routines. Thank you. Now we can stop connecting the dots with hidden declaration hacks. Yay!
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: = User Defined Attributes --- Attributes on overloads are critical. Currently fails: module test; [1] void foo(); [2] void foo(int x); template Tuple(A...) { alias A Tuple; } void main() { foreach (o; __traits(getOverloads, test, foo)) { alias Tuple!(__traits(getAttributes, o)) attrs; pragma(msg, attrs.stringof); } } Compiler outputs: () ()
Re: User Defined Attributes
How do the attributes interact with inheritance ? What happens when one inherits an attribute-decorated class ? I can picture both situations, when you would like to see the attributes inherited, and when you would prefer them dropped.
Re: User Defined Attributes
On 2012-11-06 09:20, Sönke Ludwig wrote: Wow, that's a surprise! Just yesterday I was thinking that it would be really nice to have them for a piece of code ;) But shouldn't we keep the syntax closer to normal attributes and other languages(*)? I see a lot of arguments for doing that, with the only counter-argument that they would be in the same namespace as the built-in attributes (which should not be that bad, as this is very low level language stuff). (*) i.e. @mytype or @(string) and without the '[]' I agree, I a syntax like this would have been nicer: @mtype(key : value) int a; or @mtype(key : value) int a; @mtype(value) int b; @mtype int c; -- /Jacob Carlborg
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. Hmmm, it didn't work on the most important place for my use case, function parameters: void a([test] int foo) { pragma(msg, __traits(getAttributes, foo)); } test.d(1): Error: basic type expected, not [ test.d(1): Error: found 'int' when expecting ')' test.d(1): Error: semicolon expected following function declaration test.d(1): Error: no identifier for declarator foo test.d(1): Error: semicolon expected, not ')' test.d(1): Error: Declaration expected, not ')' The reason why this is important to me is I have a nice automatic form builder given a function signature. I'd like to add things like hints about the params that my existing code can take a look at. (a problem that might remain is being able to reference the parameters outside... I use a ParameterTypeTuple and .stringof right now but that probably won't work for getAttributes. But we can always solve that later.)
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 13:08:15 UTC, Jacob Carlborg wrote: Also have a more key-value like mapping, something like this: We can always use custom types to get this kind of thing. struct key { string value; } [key(value)] foo
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: References: http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html I tried to build DMD git for dpaste, so people can play with UDA but DMD segfaults when building Phobos Program received signal SIGSEGV, Segmentation fault. 0x00403179 in ClassDeclaration::getAccess(Dsymbol*) () (gdb) bt #0 0x00403179 in ClassDeclaration::getAccess(Dsymbol*) () #1 0x00403614 in AggregateDeclaration::accessCheck(Loc, Scope*, Dsymbol*) () #2 0x00459f36 in CallExp::semantic(Scope*) () #3 0x004ccceb in ExpStatement::semantic(Scope*) () #4 0x004d0cdd in CompoundStatement::semantic(Scope*) () #5 0x0046b830 in FuncDeclaration::semantic3(Scope*) () #6 0x00448418 in FuncExp::semantic(Scope*) () #7 0x004a0a0a in TypeTypeof::semantic(Loc, Scope*) () #8 0x00499b61 in Type::trySemantic(Loc, Scope*) () #9 0x0044e16e in IsExp::semantic(Scope*) () #10 0x00427e4a in StaticIfCondition::include(Scope*, ScopeDsymbol*) () #11 0x004058e2 in ConditionalDeclaration::include(Scope*, ScopeDsymbol*) () #12 0x00405987 in StaticIfDeclaration::include(Scope*, ScopeDsymbol*) () #13 0x00403fe0 in AttribDeclaration::addMember(Scope*, ScopeDsymbol*, int) () #14 0x00405add in StaticIfDeclaration::addMember(Scope*, ScopeDsymbol*, int) () #15 0x00404015 in AttribDeclaration::addMember(Scope*, ScopeDsymbol*, int) () Well, anyways, I fetched package prepared in first post. So folks, you can play with UDA on http://dpaste.dzfl.pl - by picking DMD2 git - without messing with DMD packages in your OS :) http://dpaste.dzfl.pl/9c2e8b20 Also if I declare string with UDA inside main() I get error: http://dpaste.dzfl.pl/909a34c8
Re: User Defined Attributes
You can put the attribute on the function. There are a couple of go libraries that use struct tags in a similar way. Such as code.google.com/p/gorest On 6 Nov 2012 15:15, Adam D. Ruppe destructiona...@gmail.com wrote: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. Hmmm, it didn't work on the most important place for my use case, function parameters: void a([test] int foo) { pragma(msg, __traits(getAttributes, foo)); } test.d(1): Error: basic type expected, not [ test.d(1): Error: found 'int' when expecting ')' test.d(1): Error: semicolon expected following function declaration test.d(1): Error: no identifier for declarator foo test.d(1): Error: semicolon expected, not ')' test.d(1): Error: Declaration expected, not ')' The reason why this is important to me is I have a nice automatic form builder given a function signature. I'd like to add things like hints about the params that my existing code can take a look at. (a problem that might remain is being able to reference the parameters outside... I use a ParameterTypeTuple and .stringof right now but that probably won't work for getAttributes. But we can always solve that later.)
Re: User Defined Attributes
On 2012-11-06 14:17, Adam D. Ruppe wrote: We can always use custom types to get this kind of thing. struct key { string value; } [key(value)] foo Right, good point. But I would still like to somehow be able to name an attribute. If one just need to mark a symbol, i.e. @test void foo () {} Then one either have to use a string literal or something like a dummy variable/type. [test] void foo () {} enum test = test; [test] void foo () {} Or struct test {} [test()] void foo () {} -- /Jacob Carlborg
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 13:55:49 UTC, Rory McGuire wrote: You can put the attribute on the function. Yeah, but that's an awfully roundabout way to add an attribute to the parameter... if it went on func params: void foo([Hint(this does something)] string something) {} otherwise we'd have to do something like [ParamHint(something, this does something)] void foo(string something) {} Which isn't really ahead from the old hack of enum attr_foo_someting = Hint(); and has similar problems in matching names. It's a little better but not as good as it could be.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 14:05:46 UTC, Adam D. Ruppe wrote: On Tuesday, 6 November 2012 at 13:55:49 UTC, Rory McGuire wrote: You can put the attribute on the function. Yeah, but that's an awfully roundabout way to add an attribute to the parameter... if it went on func params: void foo([Hint(this does something)] string something) {} otherwise we'd have to do something like [ParamHint(something, this does something)] void foo(string something) {} Which isn't really ahead from the old hack of enum attr_foo_someting = Hint(); and has similar problems in matching names. It's a little better but not as good as it could be. What if the data in the attribute needs to be specific to the symbol on which the attribute is set on? Can you query the symbol from inside the attribute? What if the attribute needs to change the symbol being defined? For instance (using commonly desired syntax): @flags enum A { ... } the flags attribute would replace the declaraction of A with another enum declaration with the same name and same members, but with replaced initialization and would static assert(false, flags enum can't have initializers) if any initializers are given. The existing [data] declaration is one thing. It adds compile-time data to symbols, which is very very important, but it's not the only thing that is needed. What I described above is not quite an attribute, but an annotation. The semantics of attributes as Walter made them is perfect. The annotation should be defined like so: template myAnnotation(alias symbol, annot_args...) { // ... [myAnnoration adds this attribute] alias symbol myAnnotation; // or alias anything else if a change in necessary. } @myAnnotation(arg1, arg2, arg3) class Declaration { } here the symbol is passed to the template as the first parameter and the parameters in the parentheses are passes after it. It's basically a thin syntactic sugar over some manual (and very ugly) manual template instantiations (and mixins), so it doesn't add anything new. Annotations then become a way to statically replace declarations. This would be perfect to replace Scoped!MyClass mc; with: @scoped MyClass mc; Which looks quite like a very beautiful built-in syntax, but is actually a library solution. IMHO, Attributes as they are should stay, but annotations should be added. P.S. Thank you, Walter very very much for making attributes!!! :-)
Re: User Defined Attributes
On 2012-11-06 15:23, Gor Gyolchanyan wrote: What if the data in the attribute needs to be specific to the symbol on which the attribute is set on? Can you query the symbol from inside the attribute? What if the attribute needs to change the symbol being defined? For instance (using commonly desired syntax): @flags enum A { ... } the flags attribute would replace the declaraction of A with another enum declaration with the same name and same members, but with replaced initialization and would static assert(false, flags enum can't have initializers) if any initializers are given. The existing [data] declaration is one thing. It adds compile-time data to symbols, which is very very important, but it's not the only thing that is needed. What I described above is not quite an attribute, but an annotation. The semantics of attributes as Walter made them is perfect. The annotation should be defined like so: template myAnnotation(alias symbol, annot_args...) { // ... [myAnnoration adds this attribute] alias symbol myAnnotation; // or alias anything else if a change in necessary. } @myAnnotation(arg1, arg2, arg3) class Declaration { } here the symbol is passed to the template as the first parameter and the parameters in the parentheses are passes after it. It's basically a thin syntactic sugar over some manual (and very ugly) manual template instantiations (and mixins), so it doesn't add anything new. Annotations then become a way to statically replace declarations. This would be perfect to replace Scoped!MyClass mc; with: @scoped MyClass mc; Which looks quite like a very beautiful built-in syntax, but is actually a library solution. IMHO, Attributes as they are should stay, but annotations should be added. P.S. Thank you, Walter very very much for making attributes!!! :-) I like this proposal as well. -- /Jacob Carlborg
Re: User Defined Attributes
Am 06.11.2012 14:14, schrieb Adam D. Ruppe: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. Hmmm, it didn't work on the most important place for my use case, function parameters: void a([test] int foo) { pragma(msg, __traits(getAttributes, foo)); } sad - but its still very young feature :) im using something like an description on my methods to describe parameter features for an resource manager - something like read, write, copy, read_write etc. to have this at compiletime available by using UDAs on parameters + an compiletime generator would be absolutely briliant my vote +1 for UDAs on parameters
Re: User Defined Attributes
On 11/6/2012 4:18 AM, Max Samukha wrote: Attributes on overloads are critical. Currently fails: That should work. Will investigate.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 13:14:50 UTC, Adam D. Ruppe wrote: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. Hmmm, it didn't work on the most important place for my use case, function parameters: void a([test] int foo) { pragma(msg, __traits(getAttributes, foo)); } Hmmm, actually it doesn't work in plain function/block scope either. void a() { [test] int foo; pragma(msg, __traits(getAttributes, foo)); } Error: found 'int' when expecting ';' following statement
Re: User Defined Attributes
On 11/6/2012 4:24 AM, angel wrote: How do the attributes interact with inheritance ? What happens when one inherits an attribute-decorated class ? The attributes are for the symbol, not the type.
Re: User Defined Attributes
On 11/6/2012 6:30 AM, dennis luehring wrote: Am 06.11.2012 14:14, schrieb Adam D. Ruppe: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. Hmmm, it didn't work on the most important place for my use case, function parameters: void a([test] int foo) { pragma(msg, __traits(getAttributes, foo)); } sad - but its still very young feature :) im using something like an description on my methods to describe parameter features for an resource manager - something like read, write, copy, read_write etc. But there's already out=write, read=all of them, read_write=ref, copy=not a ref or an out. I don't know what use UDAs would be for parameters.
Re: User Defined Attributes
On 11/6/2012 5:14 AM, Adam D. Ruppe wrote: Hmmm, it didn't work on the most important place for my use case, function parameters: It didn't occur to me to enable that.
Re: User Defined Attributes
On 11/6/2012 5:57 AM, Jacob Carlborg wrote: But I would still like to somehow be able to name an attribute. If one just need to mark a symbol, i.e. @test void foo () {} Then one either have to use a string literal or something like a dummy variable/type. [test] void foo () {} Which does exactly what you ask for. enum test = test; [test] void foo () {} or: enum EEE; [EEE] void foo() { }
Re: User Defined Attributes
On 11/6/2012 7:14 AM, Tove wrote: Hmmm, actually it doesn't work in plain function/block scope either. Right, I don't see a compelling purpose for that, either.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 15:18:55 UTC, Walter Bright wrote: I don't know what use UDAs would be for parameters. It's pretty much the same as anywhere else: to add useful data for reflection. A few I'd use it for is providing user visible data like label and hint for automatic UI generation, or styling hints again for the auto ui (e.g. use a multi-line input for this string). We could also potentially put validation in there, though this may be on the type as well. Or put on info to check for availability of a username. If you do an automatic UI generator, attributes on the parameters have a lot of uses. Other than that, well, I don't know, but that's probably just because I haven't done it yet!
Re: User Defined Attributes
On 2012-11-06 16:15, Walter Bright wrote: enum test = test; [test] void foo () {} or: enum EEE; [EEE] void foo() { } First, I didn't know you could have an empty enum. Second, that was my point. I don't like the need for a dummy/empty enum, or the use of a string literal. -- /Jacob Carlborg
Re: User Defined Attributes
On 11/6/2012 5:04 AM, Jacob Carlborg wrote: I agree, I a syntax like this would have been nicer: @mtype(key : value) int a; or @mtype(key : value) int a; @mtype(value) int b; @mtype int c; Part of what I was trying to do was minimizing inventing new syntaxes. The [ ArgumentList ] invents nothing new but the brackets. Your proposal is both a new syntax, and it can only do key/value pairs - nothing else.
Re: User Defined Attributes
On 2012-11-06 16:39, Walter Bright wrote: On 11/6/2012 5:04 AM, Jacob Carlborg wrote: I agree, I a syntax like this would have been nicer: @mtype(key : value) int a; or @mtype(key : value) int a; @mtype(value) int b; @mtype int c; Part of what I was trying to do was minimizing inventing new syntaxes. The [ ArgumentList ] invents nothing new but the brackets. Your proposal is both a new syntax, and it can only do key/value pairs - nothing else. It depends on how you look at it. * @mtype - is the same syntax as the current syntax for attributes * @mtype(key : value) - Uses the above in combination with the syntax for associative array literals How about this then: @mtype(foo, 3, bar) int a; And have the argument list be optional? I really like to have a short nice looking syntax for the simple use cases, i.e. @mtype int b; -- /Jacob Carlborg
Re: User Defined Attributes
On 2012-11-06 16:42, Walter Bright wrote: I see your point, but if such was implemented that way, then the UDAs would be extremely limited, and there'd be all sorts of issues with name scoping. Pretty much all that would have to not only be reinvented, but reams of documentation would have to be crafted explaining how it is different from normal names. No, I don't think so, see one of my other replies: http://forum.dlang.org/thread/k7afq6$2832$1...@digitalmars.com?page=6#post-k7bbsu:2411ls:241:40digitalmars.com -- /Jacob Carlborg
Re: User Defined Attributes
Am 06.11.2012 16:55, schrieb Jacob Carlborg: On 2012-11-06 16:39, Walter Bright wrote: On 11/6/2012 5:04 AM, Jacob Carlborg wrote: I agree, I a syntax like this would have been nicer: @mtype(key : value) int a; or @mtype(key : value) int a; @mtype(value) int b; @mtype int c; Part of what I was trying to do was minimizing inventing new syntaxes. The [ ArgumentList ] invents nothing new but the brackets. Your proposal is both a new syntax, and it can only do key/value pairs - nothing else. It depends on how you look at it. * @mtype - is the same syntax as the current syntax for attributes * @mtype(key : value) - Uses the above in combination with the syntax for associative array literals How about this then: @mtype(foo, 3, bar) int a; And have the argument list be optional? I really like to have a short nice looking syntax for the simple use cases, i.e. @mtype int b; +1 Also, if mtype is a template, it could naturally be @mtype!(1, 2, 3). Without the '!' it would be a function that is evaluated at CT. And just @mtype would yield an alias of mtype.
Re: User Defined Attributes
On 11/6/2012 5:23 AM, nazriel wrote: I tried to build DMD git for dpaste, so people can play with UDA but DMD segfaults when building Phobos The auto tester shows it's working. http://d.puremagic.com/test-results/
Re: User Defined Attributes
Am Tue, 06 Nov 2012 09:49:42 +0100 schrieb Jakob Ovrum jakobov...@gmail.com: But, I yield until someone comes up with actual examples of how these UDAs are useful, because I can't think of anything interesting at the moment. I guess I should go read over the old discussions you linked (I remember participating, but can't remember any specifics). The std.benchmark proposal currently requires all benchmark functions to be named benchmark_name: void benchmark_stdio_write_test() {} with UDA: @benchmark(stdio write test) void benchStdioWrite(); Of course you still need that sheduleBenchmarks mixin in every module and of course it'd be nice to avoid that. But UDAs are already a big step forward.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 15:19:53 UTC, Walter Bright wrote: On 11/6/2012 7:14 AM, Tove wrote: Hmmm, actually it doesn't work in plain function/block scope either. Right, I don't see a compelling purpose for that, either. Hmm, what about library based GC annotations? [GC.NoScan] int* local_p;
Re: User Defined Attributes
On 11/6/2012 7:55 AM, Jacob Carlborg wrote: On 2012-11-06 16:39, Walter Bright wrote: On 11/6/2012 5:04 AM, Jacob Carlborg wrote: I agree, I a syntax like this would have been nicer: @mtype(key : value) int a; or @mtype(key : value) int a; @mtype(value) int b; @mtype int c; Part of what I was trying to do was minimizing inventing new syntaxes. The [ ArgumentList ] invents nothing new but the brackets. Your proposal is both a new syntax, and it can only do key/value pairs - nothing else. It depends on how you look at it. * @mtype - is the same syntax as the current syntax for attributes * @mtype(key : value) - Uses the above in combination with the syntax for associative array literals How about this then: @mtype(foo, 3, bar) int a; And have the argument list be optional? I really like to have a short nice looking syntax for the simple use cases, i.e. @mtype int b; There's a lot more you can do with the ArgumentList syntax than associative arrays. Furthermore, there remains the problem of how mtype fits into the name scoping system.
Re: User Defined Attributes
For the syntax maybe it's better something like @() instead of [], so it becomes more greppable and more easy to tell apart visually from the array literals: @(1, xx, Foo) int x; Supporting annotations for function arguments is probably an important sub-feature. Yesterday I was discussing about the bug-prone nature of foreach loops on a struct array, and one of the solutions I've suggested was a user-defined annotation for the programmer to denote that she wants to modify just the copy: struct Foo {} Foo[10] foos; foreach (@copy f; foos) { ... } With UDA syntax: foreach ([Copy] f; foos) { ... } Or: foreach (@(Copy) f; foos) { ... } But I think there's no way to tell the compiler to give a compile-time error if such annotation is not present there (unless there's ref). - Gor Gyolchanyan: @flags enum A { ... } the flags attribute would replace the declaraction of A with another enum declaration with the same name and same members, but with replaced initialization and would static assert(false, flags enum can't have initializers) if any initializers are given. I appreciate your idea (I think of user-defined attributes also as ways to extend the type system), But I know the engineer in Walter prefers extra-simple ideas, so maybe your idea will not be accepted :-) But let's see. Bye, bearophile
Re: User Defined Attributes
On 11/6/2012 8:04 AM, Johannes Pfau wrote: The std.benchmark proposal currently requires all benchmark functions to be named benchmark_name: void benchmark_stdio_write_test() {} with UDA: @benchmark(stdio write test) void benchStdioWrite(); Of course you still need that sheduleBenchmarks mixin in every module and of course it'd be nice to avoid that. But UDAs are already a big step forward. Consider that you can use a tuple generated elsewhere for a UDA: [tp] void foo(); where tp is a tuple. You can even grab the attributes from another symbol, turn them into a tuple, and apply the tuple as an attribute to a new symbol. Tuples can, of course, be sliced and concatenated. In other words, by using tuples, you can encapsulate what the attributes expand to in the same way you can change target code by changing the definition of user defined types.
Re: User Defined Attributes
On 11/6/2012 8:02 AM, Tove wrote: On Tuesday, 6 November 2012 at 15:19:53 UTC, Walter Bright wrote: On 11/6/2012 7:14 AM, Tove wrote: Hmmm, actually it doesn't work in plain function/block scope either. Right, I don't see a compelling purpose for that, either. Hmm, what about library based GC annotations? [GC.NoScan] int* local_p; I have no idea how you could make that work.
Re: User Defined Attributes
Le 06/11/2012 09:20, Sönke Ludwig a écrit : Wow, that's a surprise! Just yesterday I was thinking that it would be really nice to have them for a piece of code ;) But shouldn't we keep the syntax closer to normal attributes and other languages(*)? I see a lot of arguments for doing that, with the only counter-argument that they would be in the same namespace as the built-in attributes (which should not be that bad, as this is very low level language stuff). (*) i.e. @mytype or @(string) and without the '[]' +1 In addition, this is [] thing will require lookahead when parsing to detect if we have an expression (array literal) or a declaration.
Re: User Defined Attributes
Le 06/11/2012 08:55, Walter Bright a écrit : References: http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html Inspired by a gallon of coffee, I decided to get it implemented. It's simple, based on what D already does (CTFE and heterogeneous tuples), easy to implement, easy to understand, and doesn't break anything. It should do everything asked for in the above references (except it's not a type constructor). You can download it here and try it out: http://ftp.digitalmars.com/dmd2beta.zip As a bonus, that beta also can generate Win64 executables, and you can even symbolically debug them with VS! (Thanks to Rainer Schütze for his invaluable help with that). Here's the rather skimpy and lame spec I banged out: = User Defined Attributes --- User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them. Grammatically, a UDA is a StorageClass: StorageClass: UserDefinedAttribute UserDefinedAttribute: [ ArgumentList ] And looks like: [ 3 ] int a; [ string, 7 ]: int b; If there are multiple UDAs in scope for a declaration, they are concatenated: [ 1 ] { [ 2 ] int a; // has UDA's [1,2] [ string ] int b; // has UDA's [1,string] } UDA's can be extracted into an expression tuple using __traits: [ 'c' ] string s; pragma(msg, __traits(getAttributes, s)); prints: tuple('c') If there are no user defined attributes for the symbol, an empty tuple is returned. The expression tuple can be turned into a manipulatable tuple: template Tuple(T...) { alias T Tuple; } enum EEE = 7; [hello] struct SSS { } [3] { [4][EEE][SSS] int foo; } alias Tuple!(__traits(getAttributes, foo)) TP; pragma(msg, TP); pragma(msg, TP[2]); prints: tuple(3,4,7,(SSS)) 7 and of course the tuple types can be used to declare things: TP[3] a; // a is declared as an SSS The attribute of the type name is not the same as the attribute of the variable: pragma(msg, __traits(getAttributes, typeof(a)); prints: tuple(hello) Of course, the real value of UDA's is to be able to create user defined types with specific values. Having attribute values of basic types does not scale. The attribute tuples can be manipulated like any other tuple, and can be passed as the argument list to a template. Whether the attributes are values or types is up to the user, and whether later attributes accumulate or override earlier ones is also up to how the user interprets them. OK, I may break all the happiness of that news but . . . Tuple in D is notoriously known to be a badly designed feature. Basing more stuff on that just because we have them is short sighted and will only result in D's tuples being broken forever, several tuples implementations for more user confusion, or future major breakage. We still don't have any scheme for a stable D, feature testing or whatever, so everybody should be prepared for many new ICE (or even more fun, bugs). After we all love them or we wouldn't be using D ! Who need a programming language to be stable or reliable ? Surprise feature ! Yaw, no wonder D's toolchain is so wonderfull ! Let's not talk these awesome static code analysis tools, java would become jealous. BTW, I don't really like that syntax, but really, that isn't important.
Re: Remus
I'm learning the D language right now, and I can not say that I've missed any of these things. They may offer some 'syntactic sugar', but the D is very expressive anyway. Ex: for safe invocation I would use an assert/enforce anyway if there is a chance the object is null. The 'import package' whould be usefull though... Which language(s) did you use before? Java? ;)
Re: User Defined Attributes
Le 06/11/2012 10:07, Walter Bright a écrit : n 11/6/2012 12:59 AM, Jakob Ovrum wrote: Problem is that there's no way to do this without having the user specify which modules it should work for, like: import attributes; import a, b, c; static this() // This code cannot be automated. { initAttributes!a(); initAttributes!b(); initAttributes!c(); } Is that really a problem? I'm not sure. How can AOP be implemented on top of that ?
Re: User Defined Attributes
On 11/6/2012 8:23 AM, bearophile wrote: Supporting annotations for function arguments is probably an important sub-feature. It would be a significant extension, and so I'd like to see a compelling use case first. Yesterday I was discussing about the bug-prone nature of foreach loops on a struct array, and one of the solutions I've suggested was a user-defined annotation for the programmer to denote that she wants to modify just the copy: struct Foo {} Foo[10] foos; foreach (@copy f; foos) { ... } With UDA syntax: foreach ([Copy] f; foos) { ... } Or: foreach (@(Copy) f; foos) { ... } But I think there's no way to tell the compiler to give a compile-time error if such annotation is not present there (unless there's ref). User defined attributes cannot invent new semantics for the language. And besides, 'ref' already does what you suggest.
Re: User Defined Attributes
Am 06.11.2012 16:18, schrieb Walter Bright: On 11/6/2012 6:30 AM, dennis luehring wrote: Am 06.11.2012 14:14, schrieb Adam D. Ruppe: On Tuesday, 6 November 2012 at 07:55:51 UTC, Walter Bright wrote: User Defined Attributes (UDA) are compile time expressions that can be attached to a declaration. Hmmm, it didn't work on the most important place for my use case, function parameters: void a([test] int foo) { pragma(msg, __traits(getAttributes, foo)); } sad - but its still very young feature :) im using something like an description on my methods to describe parameter features for an resource manager - something like read, write, copy, read_write etc. But there's already out=write, read=all of them, read_write=ref, copy=not a ref or an out. and now expand that to an higher level manager that use such information for implementing(generating) runtime loading and locking strategies in a tree/graph based environment - based on the parameters needs ... i've got something like that in C++ using its own interface description language and an generator I don't know what use UDAs would be for parameters. exact the same as for every other symbol - it enriches the semantic meaning of that symbol :)
Re: User Defined Attributes
Le 06/11/2012 17:46, Walter Bright a écrit : On 11/6/2012 8:27 AM, deadalnix wrote: OK, I may break all the happiness of that news but . . . Tuple in D is notoriously known to be a badly designed feature. Basing more stuff on that just because we have them is short sighted and will only result in D's tuples being broken forever, several tuples implementations for more user confusion, or future major breakage. The only real trouble with tuples is that functions can't return them. If it is the only problem, we have a pandemic spread of hallucinogen trance amongs D users. We still don't have any scheme for a stable D, feature testing or whatever, Are you aware of the test suite and the auto-tester? Yes, I'm also aware I hit compiler bugs on a daily basis, that my codebase is full of workaround on some of them. Let's not talk these awesome static code analysis tools, java would become jealous. I have no idea what your point is. My point is that we have no tooling. Project exists, but they all ends up dead at some point or ends up not caring about compatibility that much (I'm aware of at least 3 serious D like projects that dropped dmd compatibility after spending quite a lot of time on it). The situation is really bad in that regard (many stuff are implementation defined, or even not defined at all because the implementation is known to be buggy), and adding surprise, half specified features are really not helping. If you have no idea what my point is, I'm probably wasting my time working on D.
Re: User Defined Attributes
Le 06/11/2012 17:37, Walter Bright a écrit : On 11/6/2012 8:29 AM, deadalnix wrote: In addition, this is [] thing will require lookahead when parsing to detect if we have an expression (array literal) or a declaration. Not really, as an array literal starting an expression is kinda meaningless, Not with UFCS.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 08:26:14 UTC, Walter Bright wrote: We can debate the syntax. I don't have a store set by this one. I was more interested in getting the semantics right. Anyhow, it's nice to have a working prototype to experiment with rather than a paper airplane. Yes, it is nice to have a working prototype indeed. What is not so nice in my opinion, however, is that this first prototype straight to Git master, without any prior evaluation, at a time where the general goal is to stabilize the language. What if the implementation doesn't pan out as planned? Do you want to delay the next release until the new feature has become stable? It can be a big mess to hastily revert the commits again after the same areas might have been touched by other, unrelated sets of changes. This is exactly what branches are good for. People can experiment with the new additions and shortcomings can be fixed, and then, if everything looks solid, the branch can be merged back into master – without affecting work on the main branch in the meantime (it has been three months since the last release, and there are quite a few open regressions). Even Andrei submits pull requests for any non-trivial Phobos changes. Might I suggest adopting a similar policy for DMD, at least when language changes/additions are concerned? David
Re: User Defined Attributes
On 11/6/2012 8:47 AM, bearophile wrote: Walter Bright: It would be a significant extension, and so I'd like to see a compelling use case first. Right. Combined with the trait to read function arguments, it's useful to add semantics to function arguments. This is good. Ok, I ask again, what use case for a UDA is there for function parameters? (Note that IDL isn't it, as D already has enough parameter attributes to support IDL.) User defined attributes cannot invent new semantics for the language. Right, that's my point :-) So it cannot work for the use case you suggested. I'm still asking for a compelling use case. And besides, 'ref' already does what you suggest. Nope. I have discussed the topic here: http://forum.dlang.org/thread/znbtczbgipqqzllaf...@forum.dlang.org ref is useful to denote Case2 of that post of mine. But the @copy annotation I was talking here is the very uncommon (but unfortunately often used by mistake, and common source of bugs) Case3. I don't see how having the user add a UDA is better than having the user add const.
Re: User Defined Attributes
Le 06/11/2012 16:15, Walter Bright a écrit : On 11/6/2012 5:14 AM, Adam D. Ruppe wrote: Hmmm, it didn't work on the most important place for my use case, function parameters: It didn't occur to me to enable that. It should work everywhere or not work at all.
Re: User Defined Attributes
Enjoying playing with the new stuff. UDAs appear to work on class, struct and global methods, but not interface methods. Any reason for the omission? Would be great to have them on interface methods too - for example to define COM dispids.
Re: User Defined Attributes
On 11/6/2012 9:01 AM, deadalnix wrote: Le 06/11/2012 17:37, Walter Bright a écrit : On 11/6/2012 8:29 AM, deadalnix wrote: In addition, this is [] thing will require lookahead when parsing to detect if we have an expression (array literal) or a declaration. Not really, as an array literal starting an expression is kinda meaningless, Not with UFCS. You have a point.
Re: User Defined Attributes
On 11/6/2012 9:00 AM, dennis luehring wrote: 1. what if my needs are beyond D? for example my idl allows me to define a type based query source for parameters CalculateStuff( TypeX [source=\\placement\(typeA|typeB|typeC)] my_usage ) this defines the source of assignable objects to this method Has this capability ever been used? 2. what is the reason for stopping right before parameters? (except less coding on your side) It adds significant complexity. I don't think it's a good idea to add significant complexity to the language without a compelling use case. It needs to be something more than just being nice.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 16:41:22 UTC, Walter Bright wrote: It would be a significant extension, and so I'd like to see a compelling use case first. What do you consider to be compelling use cases for UDAs on functions? Going back to the links on the original post, we have: I have numerous systems that need to scan the module for things marked accordingly to automate bindings to their respective systems. Putting them on parameters also helps with this. Script languages have to deal with parameters. Editors might. And, of course, I've already talked about automatic UI generation. Here's another one: named parameters. Of course, there's D names, but suppose you have to hook into another naming scheme that uses characters that aren't valid D names? An external system might send you log-in?user-id=foo. You are doing a library to automatically call a class: class Handler { [ExternalName(log-in)] /* we can do this now */ void logIn([ExternalName(user-id)] string userId) {} /* but the parameter, which is the same concept, doesn't work */ }
Re: User Defined Attributes
On 11/6/2012 9:06 AM, deadalnix wrote: Le 06/11/2012 16:15, Walter Bright a écrit : On 11/6/2012 5:14 AM, Adam D. Ruppe wrote: Hmmm, it didn't work on the most important place for my use case, function parameters: It didn't occur to me to enable that. It should work everywhere or not work at all. You can't have @pure attributes on function parameters, either. Parameters don't work like regular declarations, never have, and I don't know of a language where they do. They even have a different grammar.
Re: User Defined Attributes
On 11/6/2012 9:07 AM, John Chapman wrote: UDAs appear to work on class, struct and global methods, but not interface methods. Any reason for the omission? Would be great to have them on interface methods too - for example to define COM dispids. Can you show an example code snippet?
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 17:16:34 UTC, Adam D. Ruppe wrote: [ExternalName(log-in)] /* we can do this now */ void logIn([ExternalName(user-id)] string userId) BTW we could conceivably do: [ExternalName(log-in), ParameterAttribute!(userId)(ExternalName(user-id)] void logIn(string userId) {} Where the ParameterAttribute simply matches up the param by name or by position (if you pass an int instead of string) and puts the other argument in that map. When you scan the function for attributes, you keep your eye open for that ParameterAttribute thingy and match it up in the library. So if it is too painful to put it in the compiler, we could make it work in the library.
Re: User Defined Attributes
Am 06.11.2012 18:14, schrieb Walter Bright: On 11/6/2012 9:00 AM, dennis luehring wrote: 1. what if my needs are beyond D? for example my idl allows me to define a type based query source for parameters CalculateStuff( TypeX [source=\\placement\(typeA|typeB|typeC)] my_usage ) this defines the source of assignable objects to this method Has this capability ever been used? all the while - the complete object-to-object lifecycle of composits etc. is managed by this - no coded object creation is happening its partially based on the naked object pattern the next step will be a complete managed(and hopefully more efficient) loading/locking strategy - but still in around 800k lines of C++ :(
Re: User Defined Attributes
Am 06.11.2012 18:32, schrieb David Nadlinger: On Tuesday, 6 November 2012 at 17:00:27 UTC, Walter Bright wrote: Ok, I ask again, what use case for a UDA is there for function parameters? (Note that IDL isn't it, as D already has enough parameter attributes to support IDL.) What »IDL« are you referring to here? At least as far as I am aware, IDL usually just refers to an »interface definition language« in general, so I'm not quite sure what you mean if you are talking about »enough to support IDL«. Actually, the Thrift IDL would be a perfect example of how attributes on parameters can be useful. A simple service definition in a .thrift could look like this: --- service Calculator { i32 calculate(1:i32 a, 2:i32 b, 3:Op op) } perfect example - thx alot
Re: User Defined Attributes
On 2012-11-06 17:22, Walter Bright wrote: Consider that you can use a tuple generated elsewhere for a UDA: [tp] void foo(); where tp is a tuple. You can even grab the attributes from another symbol, turn them into a tuple, and apply the tuple as an attribute to a new symbol. Tuples can, of course, be sliced and concatenated. In other words, by using tuples, you can encapsulate what the attributes expand to in the same way you can change target code by changing the definition of user defined types. Then allow something like this: @(tp) Or @foo(tp) -- /Jacob Carlborg
Re: User Defined Attributes
On 11/6/2012 9:52 AM, bearophile wrote: // Case3 (uncommon) void main() { auto data = [0, 1, 2, 3]; foreach (@copy x; data) writeln(++x); } x is a value type, and it is already copied. And if you did want to copy it, foreach (x; data) { auto copy = x; writeln(++copy); } I don't see what the annotation buys you, even if it could be made to work.
Re: User Defined Attributes
On 11/6/2012 10:01 AM, David Nadlinger wrote: On Tuesday, 6 November 2012 at 17:51:28 UTC, Walter Bright wrote: On 11/6/2012 9:32 AM, David Nadlinger wrote: service Calculator { i32 calculate(1:i32 a, 2:i32 b, 3:Op op) What does this mean? That 'a' is the first parameter and has type i32? It means that ›a‹ has type i32 Ok, but a type is not a UDA g. and is the parameter with ID 1. The parameter list could have also been (42:i32 a, 5:i32 b, 1:Op op). If no ids are specified, negative ones are auto-assigned by the compiler, starting from -1. Why isn't 'a' the ID?
Re: User Defined Attributes
On 2012-11-06 18:00, David Nadlinger wrote: Yes, it is nice to have a working prototype indeed. What is not so nice in my opinion, however, is that this first prototype straight to Git master, without any prior evaluation, at a time where the general goal is to stabilize the language. Yes, very good point. I don't see why this hasn't been done before, it's dead easy. Just use: $ git checkout -b uda # code $ git commit -a -m Add support for user defined attributes $ git push origin uda Walter, why aren't you using branches for these kind of things? -- /Jacob Carlborg
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 18:06:15 UTC, Walter Bright wrote: On 11/6/2012 10:01 AM, David Nadlinger wrote: On Tuesday, 6 November 2012 at 17:51:28 UTC, Walter Bright wrote: On 11/6/2012 9:32 AM, David Nadlinger wrote: service Calculator { i32 calculate(1:i32 a, 2:i32 b, 3:Op op) What does this mean? That 'a' is the first parameter and has type i32? It means that ›a‹ has type i32 Ok, but a type is not a UDA g. That was never my point. I could have also just said »Parameters to Thrift RPC methods have numerical IDs«, but I though a code example might be clearer. Apparently, I was wrong. ;) Why isn't 'a' the ID? a is just a name used for documentation purposes – they show up in target language code generated by the Thrift compiler from the IDL file, for implementations which rely on code generation [1]. On the wire, all struct fields and method parameters are tagged with integer IDs, and those are actually what's used for (de-)serializations. This use of IDs is a common feature of »high-performance« RPC protocols designed to support interface evolution, e.g. Google's protobuf makes use of them as well. David [1] The compiler module for D only translates type and service definitions to D structs/interfaces, the rest happens using CTFE magic, which enables use of Thrift without writing .thrift files (in fact, they can be generated _from_ D code using CTFE). In theory, the compiler could be completely replaced using ImportStatements and CTFE, but I never got that out of the prototype stage due to compiler bugs.
Re: User Defined Attributes
On 11/6/2012 10:01 AM, Jacob Carlborg wrote: What's the issue with the name scoping system? That the user defined attributes will conflict with already existing attributes? You'll have the same problem with keywords. Perhaps that's why attributes where created, to have a new namespace for keywords. Even if they might not be the same internally for the compiler it's the same for the user/developer. Then all UDAs must exist in some shared global name space, and scoping and encapsulation becomes like it is in C, i.e. every_body_writes_their_names_like_this and hopes it doesn't conflict with someone else's names.
Re: User Defined Attributes
On 2012-11-06 19:16, Walter Bright wrote: Then all UDAs must exist in some shared global name space, and scoping and encapsulation becomes like it is in C, i.e. every_body_writes_their_names_like_this and hopes it doesn't conflict with someone else's names. No, what's the difference between this: @every_body_writes_their_names_like_this int a; And [every_body_writes_their_names_like_this] int a; None. -- /Jacob Carlborg
Re: User Defined Attributes
Le 06/11/2012 19:02, Walter Bright a écrit : On 11/6/2012 9:34 AM, dennis luehring wrote: can't you please give us a bad-usage example why it is/should be forbidden to use UDA on parameters (and please - we are not talking about pure, in, out and stuff like that) I believe this is the wrong question. For a new feature, the question should be why should it be included, not why shouldn't it be included. No. It is needed to annotate symbols, uses cases are numerous. Now, if an exception is added, the exception should be justified.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 18:16:15 UTC, Walter Bright wrote: Then all UDAs must exist in some shared global name space, and scoping and encapsulation becomes like it is in C, i.e. every_body_writes_their_names_like_this and hopes it doesn't conflict with someone else's names. You are right, UDAs must definitely leverage D's module system for encapsulation/disambiguation. Use of string literals (which are intrinsically »global«) as annotations needs to be explicitly discouraged. David
Re: User Defined Attributes
Le 06/11/2012 19:19, Jacob Carlborg a écrit : On 2012-11-06 19:16, Walter Bright wrote: Then all UDAs must exist in some shared global name space, and scoping and encapsulation becomes like it is in C, i.e. every_body_writes_their_names_like_this and hopes it doesn't conflict with someone else's names. No, what's the difference between this: @every_body_writes_their_names_like_this int a; And [every_body_writes_their_names_like_this] int a; None. Let me suggest what have already been suggested by others : @identifier(parameters) identifier is resolved as any identifier is. It allow for disambiguation. It also allow for a lib to provide its own attributes types without colliding which other (it is easy to filter the tuple for attribute with the right type).
Re: User Defined Attributes
Am 06.11.2012 17:41, schrieb Walter Bright: On 11/6/2012 8:23 AM, bearophile wrote: Supporting annotations for function arguments is probably an important sub-feature. It would be a significant extension, and so I'd like to see a compelling use case first. Having seen how annotations for function arguments in Java 8 might look like, and the annotations everywhere that we have in the enterprise frameworks, I am weary of such support. -- Paulo
Re: User Defined Attributes
On 11/6/2012 10:19 AM, Jacob Carlborg wrote: No, what's the difference between this: @every_body_writes_their_names_like_this int a; And [every_body_writes_their_names_like_this] int a; None. You're right, there is none. That's why using type names as attributes is more scalable and robust. I understand your desire to have attributes be implicitly declared, but I think that implicit declarations have historically been seductive, and much later were realized to be a mistake. This pattern has happened over and over :-) For example: @seperate and sometime later: @separate How long will it be before that bug is noticed?
Re: User Defined Attributes
Am 06.11.2012 17:26, schrieb Walter Bright: On 11/6/2012 8:02 AM, Tove wrote: On Tuesday, 6 November 2012 at 15:19:53 UTC, Walter Bright wrote: On 11/6/2012 7:14 AM, Tove wrote: Hmmm, actually it doesn't work in plain function/block scope either. Right, I don't see a compelling purpose for that, either. Hmm, what about library based GC annotations? [GC.NoScan] int* local_p; I have no idea how you could make that work. I can only see it work if the runtime is aware of magic annotations, which are kept in the binary. -- Paulo
Re: User Defined Attributes
Walter Bright: First of all, assume I know how to use and abuse foreach in all the common and uncommon cases. So in this discussion we can assume we both know well enough what we are talking about. What I am discussing about is a real problem in real D code, a bug-prone characteristic of foreach. We may accept the situation like it is, and do nothing, or we may want to improve the situation. But this doesn't change the fact that there is a problem in the D design of foreach loops when you scan an array of structs. This problem is recognized by several other persons in the D community, it's not a creation of my mind. That said, let me try again to explain the problem. // Case3 (uncommon) void main() { auto data = [0, 1, 2, 3]; foreach (@copy x; data) writeln(++x); } x is a value type, and it is already copied. And if you did want to copy it, foreach (x; data) { auto copy = x; writeln(++copy); } I don't see what the annotation buys you, even if it could be made to work. The point of Case3 is not that I want to copy it again. The annotation by itself buys you nothing. But he annotation is not meant to be the only change in D. There are two changes that need to happen at the same time: Change1) Make this a compile-time error, this means if you write this code, the compiler refuses your code statically. So x despite not being const is like being const, because the compiler does not let you modify it inside the loop, if you try, it gives you an error (so maybe it's simpler to implement this Change1 really as putting const on default on x even if you don't write const there. C# language is designed this way!): auto data = [1, 2, 3]; foreach (x; data) x++; // compilation error here Change2) Introduce an annotation like @mutable to denote Case3 (I have replaced @copy with @mutable to make this explanation more clear for you, so maybe @mutable is really a better name for this idea). This means this is accepted, it's like saying that x is not const: foreach (@mutable x; data) writeln(++x); // OK Why I have suggested this pair of changes? The only purpose of those two changes is to remove one bug-prone situation from D code. The situation is this: struct Foo { int x; } auto data = [Foo(1), Foo(2), Foo(3)]; foreach (f; data) f.x++; What is the programmer trying to write there? Was she trying to change the structs inside data (Case2)? Or was she trying to modify just their copy (Case3)? The problem is that usually programmers want Case1 or Case2, they most times do not want to write a Case3. But it's very easy to forget ref. So the programmer wants to write a Case2 but often writes a Case3 by mistake. The combined presence of Change1 and Change2 removes this source of errors. Because now if you forget ref the compiler refuses your code statically. If you want Case3 you add a @copy. In most cases you really meant to use a Case2 so you add ref and the D compiler has caught your bug! If you were trying to write a Case1 you didn't put inside the loop code that modifies the struct, so the error of Change1 is not triggered and you need no @copy nor ref. I have written probably 250_000+ lines of good-quality D1/D2 code, and bugs like this are still present in my code, so I'd like to remove them from D once and for all: struct Foo { int x; } auto data = [Foo(1), Foo(2), Foo(3)]; foreach (f; data) f.x++; Bye, bearophile
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 17:17:50 UTC, Walter Bright wrote: On 11/6/2012 9:06 AM, deadalnix wrote: Le 06/11/2012 16:15, Walter Bright a écrit : On 11/6/2012 5:14 AM, Adam D. Ruppe wrote: Hmmm, it didn't work on the most important place for my use case, function parameters: It didn't occur to me to enable that. It should work everywhere or not work at all. You can't have @pure attributes on function parameters, either. Parameters don't work like regular declarations, never have, and I don't know of a language where they do. They even have a different grammar. C# allows custom attributes on function parameters, including the return value. Actually, it allows custom meta-data everywhere. See a use case here http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.aspx. I believe Java does the same.
Re: User Defined Attributes
On Tuesday, 6 November 2012 at 18:36:54 UTC, Walter Bright wrote: For example: @seperate and sometime later: @separate How long will it be before that bug is noticed? This doesn't put the @-syntax out of the game, though: @attribute could just be equivalent to @(attribute) and look up attribute in the local scope, following the usual rules. This would look much better than the bracket syntax, at least in my opinion, and avoid confusion with array literals. David
Re: User Defined Attributes
On 11/6/2012 10:10 AM, Jacob Carlborg wrote: On 2012-11-06 18:00, David Nadlinger wrote: Yes, it is nice to have a working prototype indeed. What is not so nice in my opinion, however, is that this first prototype straight to Git master, without any prior evaluation, at a time where the general goal is to stabilize the language. Yes, very good point. I don't see why this hasn't been done before, it's dead easy. Just use: $ git checkout -b uda # code $ git commit -a -m Add support for user defined attributes $ git push origin uda Walter, why aren't you using branches for these kind of things? Because I still think in a linear fashion :-)
Re: User Defined Attributes
On 11/6/2012 4:18 AM, Max Samukha wrote: Attributes on overloads are critical. Currently fails: Found fixed. Thanks!