digitalmars.D - So, User-Defined Attributes
- Philippe Sigaud (47/47) Jan 04 2013 OK, now that 2.061 is out, we have User-Defined Attributes (UDAs).
- Jacob Carlborg (7/17) Jan 04 2013 And here, nicely rendered:
- Jacob Carlborg (11/23) Jan 04 2013 No, basically anything that can be put in a tuple can be used as an UDA....
- Max Samukha (2/4) Jan 04 2013 s/we will rapidly need/we have needed for years
- Philippe Sigaud (34/34) Jan 04 2013 So, I'm testing how to transfer UDA from one symbol to another.
- Max Samukha (13/47) Jan 04 2013 transferAttributes attaches the attributes to the local
- Philippe Sigaud (8/32) Jan 04 2013 The declaration. The type, I guess I'd use an alias. Though, I guess the
- Max Samukha (8/36) Jan 04 2013 Don't think so.
- Walter Bright (5/7) Jan 04 2013 alias provides a way to provide an alternate name for a symbol. It would...
- Philippe Sigaud (4/13) Jan 04 2013 The (future) documentation says attributes can be used with declarations...
- Walter Bright (2/3) Jan 04 2013 Module declarations aren't declarations.
- Max Samukha (2/6) Jan 04 2013 They conceptually are.
- Philippe Sigaud (2/3) Jan 04 2013 Great quote :)
- Timon Gehr (7/11) Jan 06 2013 Walter often argues in terms of DMD implementation details.
- Philippe Sigaud (4/22) Jan 06 2013 PoV. It's just funny expressed that way.
- Max Samukha (13/23) Jan 04 2013 I know what the intended semantics of alias is. But the reality
- Walter Bright (5/14) Jan 04 2013 I'm not really sure if this is an issue or not. I'll have to think about...
- Walter Bright (11/12) Jan 04 2013 Remember, attributes are attached to the declaration. They are not trans...
- Andrei Alexandrescu (3/15) Jan 04 2013 For transfer templates are better than attributes.
- Walter Bright (3/4) Jan 04 2013 Sure, but I wanted to illustrate what was happening. Templates tend to o...
- Philippe Sigaud (17/34) Jan 04 2013 Yes, I know. I just want to automate the process. I want a function or s...
- Era Scarecrow (22/33) Jan 04 2013 This is sorta like tuples; But from the brief summaries I cannot
- Jacob Carlborg (13/23) Jan 04 2013 It could be used for serialization, for example. Have a look at my
- Johannes Pfau (10/21) Jan 05 2013 One example is std.benchmark. It currently detects if a function is a
- Philippe Sigaud (11/11) Jan 05 2013 Clojure uses its metadata (attached to values, though, not declaration) ...
- Jacob Carlborg (6/15) Jan 05 2013 Just for the record, the extra parentheses are not needed:
- Philippe Sigaud (17/20) Jan 05 2013 Good to know. I tested it with basic values and this fails:
- Jacob Carlborg (22/38) Jan 05 2013 No, that's by design. When I added that syntax first but I was asked to
- Philippe Sigaud (10/25) Jan 05 2013 I find it strange that @MyType ... is OK, but not @3, when, at the same
- Walter Bright (5/6) Jan 05 2013 This is as designed, not a bug. The attribute must start with a @( or
- Philippe Sigaud (4/9) Jan 05 2013 That, I can understand.
- Walter Bright (3/4) Jan 05 2013 Because it's looking for an expression inside the parents, and int is no...
- Philippe Sigaud (11/16) Jan 05 2013 Well, first that would be nice to have the grammar online :)
- Jacob Carlborg (4/5) Jan 05 2013 Yeah, still waiting for that pull request to be merged.
- Domain (7/10) Jan 05 2013 UDA can not apply to function argument?
- Walter Bright (2/14) Jan 05 2013 Currently, no.
- Philippe Sigaud (7/11) Jan 06 2013 Walter, what is the official way to return an attributed value?
- Walter Bright (3/9) Jan 06 2013 Values do not have attributes. Attributes are attached to symbols - not ...
- Jacob Carlborg (15/21) Jan 06 2013 Don't know if this is what you want but:
- Philippe Sigaud (24/36) Jan 06 2013 I just want to be able to return an attributed something. How can a
- Jacob Carlborg (4/27) Jan 06 2013 Basically, yes. I haven't been able figured out something else.
- Jacob Carlborg (4/39) Jan 06 2013 You can perhaps encapsulate this in a mixin?
- Philippe Sigaud (11/20) Jan 06 2013 That would mean two mixins, one internal and one external. Plus, that me...
- Jacob Carlborg (13/23) Jan 06 2013 Yeah, if you want to work with UDA's you need to work with symbols, not
- Philippe Sigaud (7/10) Jan 06 2013 That was the explanation I needed: UDA are attached to symbols. Now that...
- Philippe Sigaud (5/7) Jan 06 2013 Damn tab.
- Timon Gehr (5/8) Jan 06 2013 This works:
-
Andrei Alexandrescu
(4/7)
Jan 06 2013
For designing attributes that navigate with types - bearophile (8/10) Jan 06 2013 There's an interesting cognitive impercetion phenomena here,
- Philippe Sigaud (7/14) Jan 06 2013 Care to show a small example?
- deadalnix (3/12) Jan 06 2013 Isn't it better to achieve this with a template ?
- Timon Gehr (2/13) Jan 06 2013 No, it is equivalent.
- deadalnix (2/6) Jan 06 2013 And mytype is an expression ?????
- Philippe Sigaud (2/12) Jan 06 2013 Same thought here.
- Timon Gehr (8/15) Jan 06 2013 Sure!
- Walter Bright (2/9) Jan 06 2013 Parsing happens before semantic analysis. Hence, MyType looks like an ex...
- deadalnix (3/16) Jan 06 2013 OK, but if int is invalid, should semantic analysis reject MyType
- Walter Bright (3/16) Jan 06 2013 Tuples accept both types and expressions, and the semantic analyzer load...
- Timon Gehr (13/25) Jan 06 2013 Sure, that is how the compiler currently works. The compiler is an
- Timon Gehr (3/6) Jan 06 2013 dustmite ftw.
- Walter Bright (2/4) Jan 06 2013 Thank you.
- Philippe Sigaud (6/8) Jan 06 2013 I humbly concur. Walter, you yourself presented UDAs as 'linking the dot...
- Walter Bright (2/6) Jan 06 2013 Well, I am glad to see people using it.
- Walter Bright (4/6) Jan 06 2013 Sorry about that, but 2.061 has been available for 2 months in beta. We ...
- Timon Gehr (14/22) Jan 06 2013 No problem. There will be some way to get it to compile. The reduced
- Walter Bright (14/18) Jan 06 2013 A huge source of fwd ref problems was not at all about symbol lookup. It...
- Era Scarecrow (26/42) Jan 07 2013 I've had certain headaches from that as well trying to make my
- Era Scarecrow (12/28) Jan 06 2013 Yes I understand how you can attach some information using a
OK, now that 2.061 is out, we have User-Defined Attributes (UDAs). Except, there is no doc on them, no explanation, nothing. For people who did not follow the monstrous threads in November, it's as if UDA do not exist. Myself, I upgraded from 2.060 only yesterday, and I never used them. Heck, I do not even know their syntax. This thread is for people like me, who wonder what UDA are, and what can be done with them. Jacob Carlborg wrote documentation, but it's not merged into dlang.org yet, AFAICT. Here it is: https://github.com/jacob-carlborg/d-programming-language.org/commit/bddbdf18353203ba12d8e0e44391e8b6a031b91a Here is the executive summary: 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. Syntax: (3) int a; ("string", 7) int b; enum Foo; Foo int c; struct Bar { int x; } Bar(3) int d; From that, I get we can put any CT symbol (even a value) as an attribute. I thought we were restricted to user defined types. To query them, use __traits(getAttributes, symbol) ('c') string s; __traits(getAttributes, s) this gives a tuple of attributes, that can be manipulated as a template tuple parameter (the 'raw' tuples). Jacob, you doc says UDA are (grammatically) treated as storage classes. Can we do: class C { (3, "hello"): int a; double d; } And get both a and d with the same UDAs? [Answer: silly me, I have 2.061. Yes, that works, both C.a and C.d have (3, "hello") as an attribute] My own rapid reading tells me we will rapidly need good tuple manipulations templates in Phobos. We have mapping and filtering (I guess?), but overloading, discarding, dropping and folding will be needed also.
Jan 04 2013
On 2013-01-04 16:45, Philippe Sigaud wrote:OK, now that 2.061 is out, we have User-Defined Attributes (UDAs). Except, there is no doc on them, no explanation, nothing. For people who did not follow the monstrous threads in November, it's as if UDA do not exist. Myself, I upgraded from 2.060 only yesterday, and I never used them. Heck, I do not even know their syntax. This thread is for people like me, who wonder what UDA are, and what can be done with them. Jacob Carlborg wrote documentation, but it's not merged into dlang.org yet, AFAICT. Here it is: https://github.com/jacob-carlborg/d-programming-language.org/commit/bddbdf18353203ba12d8e0e44391e8b6a031b91aAnd here, nicely rendered: https://dl.dropbox.com/u/18386187/attribute.html#uda There's also documentation for the Traits section but nothing which isn't available on the Attribute section. -- /Jacob Carlborg
Jan 04 2013
On 2013-01-04 16:45, Philippe Sigaud wrote:Syntax: (3) int a; ("string", 7) int b; enum Foo; Foo int c; struct Bar { int x; } Bar(3) int d; From that, I get we can put any CT symbol (even a value) as an attribute. I thought we were restricted to user defined types.No, basically anything that can be put in a tuple can be used as an UDA. I'm wondering if we want to add a meta attribute to Phobos or druntime (object.d). Some thing like: enum attribute; attribute struct Foo { } Now, by convention "Foo" is an attribute and should only be used as an attribute. We could also add some functions to std.traits for querying UDA that takes advantage of this attribute. -- /Jacob Carlborg
Jan 04 2013
On Friday, 4 January 2013 at 15:45:21 UTC, Philippe Sigaud wrote:My own rapid reading tells me we will rapidly need good tuple manipulations templates in Phobos.s/we will rapidly need/we have needed for years
Jan 04 2013
So, I'm testing how to transfer UDA from one symbol to another. ``` auto transferAttributes(alias origin, To)(To t) { (__traits(getAttributes, origin)) To temp = t; pragma(msg, __traits(getAttributes, temp)); return temp; } void main() { (3, "hello") int i = 10; writeln("[",__traits(getAttributes, i), "]"); double d = 3.14; auto d2 = transferAttributes!(i)(d); // Doesn't work writeln("[",__traits(getAttributes, d2), "]"); // Works: (__traits(getAttributes, i)) double d3 = 3.14; writeln("[",__traits(getAttributes, d3), "]"); } ``` Begins at the end: d3 (a double) indeed ends up as having i (an int) attributes. All is well and good. But transferAttributes does not work: inside its scope, temp has the attributes from origin, but not when it gets out. Also, dropping the auto return is not accepted by the compiler, even though it seems natural for me: (__traits(getAttributes, origin)) To transferAttributes(alias origin, To)(To t) { (__traits(getAttributes, origin)) To temp = t; ... 'origin' is a template parameter and should be reachable to determine the return type.
Jan 04 2013
On Friday, 4 January 2013 at 16:04:59 UTC, Philippe Sigaud wrote:So, I'm testing how to transfer UDA from one symbol to another. ``` auto transferAttributes(alias origin, To)(To t) { (__traits(getAttributes, origin)) To temp = t; pragma(msg, __traits(getAttributes, temp)); return temp; } void main() { (3, "hello") int i = 10; writeln("[",__traits(getAttributes, i), "]"); double d = 3.14; auto d2 = transferAttributes!(i)(d);transferAttributes attaches the attributes to the local declaration. I'd be surprised if they were copied to the outer declaration. Or did you mean attributing the return *type*?// Doesn't work writeln("[",__traits(getAttributes, d2), "]"); // Works: (__traits(getAttributes, i)) double d3 = 3.14; writeln("[",__traits(getAttributes, d3), "]"); } ``` Begins at the end: d3 (a double) indeed ends up as having i (an int) attributes. All is well and good. But transferAttributes does not work: inside its scope, temp has the attributes from origin, but not when it gets out. Also, dropping the auto return is not accepted by the compiler, even though it seems natural for me: (__traits(getAttributes, origin)) To transferAttributes(alias origin, To)(To t) { (__traits(getAttributes, origin)) To temp = t; ... 'origin' is a template parameter and should be reachable to determine the return type.That's a bug. Anyway, you are attributing the function declaration here, not the return type, which is another problem as it looks we do not have a syntax for that and "auto" is required: auto foo() { attr struct S {} return S.init; }
Jan 04 2013
Max:transferAttributes attaches the attributes to the local declaration. I'd be surprised if they were copied to the outer declaration. Or did you mean attributing the return *type*?The declaration. The type, I guess I'd use an alias. Though, I guess the alias syntax limitations would probably forbid that. So yes, the local declaration is attributed, that works. How do I propagate the attribute to the returned value? Also, dropping the auto return is not accepted by the compiler, even thoughAlready filed?it seems natural for me: (__traits(getAttributes, origin)) To transferAttributes(alias origin, To)(To t) { (__traits(getAttributes, origin)) To temp = t; ... 'origin' is a template parameter and should be reachable to determine the return type.That's a bug.Anyway, you are attributing the function declaration here, not the return typeHmm. Would (attr) { ReturnType } functionName (...) work?, which is another problem as it looks we do not have a syntax for that and "auto" is required: auto foo() { attr struct S {} return S.init; }
Jan 04 2013
On Friday, 4 January 2013 at 17:11:04 UTC, Philippe Sigaud wrote:The declaration. The type, I guess I'd use an alias. Though, I guess the alias syntax limitations would probably forbid that. So yes, the local declaration is attributed, that works. How do I propagate the attribute to the returned value?I think you cannot.Also, dropping the auto return is not accepted by the compiler, even thoughDon't think so.Already filed?it seems natural for me: (__traits(getAttributes, origin)) To transferAttributes(alias origin, To)(To t) { (__traits(getAttributes, origin)) To temp = t; ... 'origin' is a template parameter and should be reachable to determine the return type.That's a bug.It looks we simply cannot modify existing declarations with UDAs. (attr) alias foo = bar; // (attr) is ignored. It is inconsistent with builtin attributes, which can create modified declarations out of existing ones. I am not sure whether it is a real problem.Anyway, you are attributing the function declaration here, not the return typeHmm. Would (attr) { ReturnType } functionName (...) work?
Jan 04 2013
On 1/4/2013 9:48 AM, Max Samukha wrote:It looks we simply cannot modify existing declarations with UDAs. (attr) alias foo = bar; // (attr) is ignored.alias provides a way to provide an alternate name for a symbol. It wouldn't be an alternate name if it had different attributes. Trying to make such work would have serious semantic consequences. Hence, no, you cannot use alias to modify the attributes.
Jan 04 2013
On Fri, Jan 4, 2013 at 9:40 PM, Walter Bright <newshound2 digitalmars.com>wrote:On 1/4/2013 9:48 AM, Max Samukha wrote:The (future) documentation says attributes can be used with declarations. I tried to use one before a module declaration but it didn't work. Is that a bug or are module declarations not 'real' declarations?It looks we simply cannot modify existing declarations with UDAs. (attr) alias foo = bar; // (attr) is ignored.alias provides a way to provide an alternate name for a symbol. It wouldn't be an alternate name if it had different attributes. Trying to make such work would have serious semantic consequences. Hence, no, you cannot use alias to modify the attributes.
Jan 04 2013
On 1/4/2013 12:49 PM, Philippe Sigaud wrote:Is that a bug or are module declarations not 'real' declarations?Module declarations aren't declarations.
Jan 04 2013
On Friday, 4 January 2013 at 20:58:42 UTC, Walter Bright wrote:On 1/4/2013 12:49 PM, Philippe Sigaud wrote:They conceptually are.Is that a bug or are module declarations not 'real' declarations?Module declarations aren't declarations.
Jan 04 2013
On Fri, Jan 4, 2013 at 9:58 PM, Walter Bright <newshound2 digitalmars.com>wrote:Module declarations aren't declarations.Great quote :)
Jan 04 2013
On 01/04/2013 11:43 PM, Philippe Sigaud wrote:On Fri, Jan 4, 2013 at 9:58 PM, Walter Bright <newshound2 digitalmars.com <mailto:newshound2 digitalmars.com>> wrote: Module declarations aren't declarations. Great quote :)Walter often argues in terms of DMD implementation details. ... struct ModuleDeclaration { Identifier *id; ...
Jan 06 2013
On Fri, Jan 4, 2013 at 9:58 PM, Walter Bright<newshound2 digitalmars.com <mailto:newshound2 **digitalmars.com<newshound2 digitalmars.com>>>PoV. It's just funny expressed that way. I keep forgetting modules are not first-class in D (it's not a criticism, I don't what I'd do with first-class modules)wrote: Module declarations aren't declarations. Great quote :)Walter often argues in terms of DMD implementation details. ... struct ModuleDeclaration { Identifier *id; ... Too low-level, I suppose ;) What he said is also true from the grammar
Jan 06 2013
On Friday, 4 January 2013 at 20:40:39 UTC, Walter Bright wrote:On 1/4/2013 9:48 AM, Max Samukha wrote:I know what the intended semantics of alias is. But the reality is slightly different. See below.It looks we simply cannot modify existing declarations with UDAs. (attr) alias foo = bar; // (attr) is ignored.alias provides a way to provide an alternate name for a symbol.It wouldn't be an alternate name if it had different attributes. Trying to make such work would have serious semantic consequences. Hence, no, you cannot use alias to modify the attributes.You can: public struct S { } private alias S S2; // visibility attribute is changed. Type modifiers: alias const(S) S2; // mutability attribute is changed. I am not saying that UDAs should be designed so that they could modify the aliased "symbols" (that would be a fatality) - just noting that alias is already NOT a plain alternative name.
Jan 04 2013
On 1/4/2013 2:03 PM, Max Samukha wrote:On Friday, 4 January 2013 at 20:40:39 UTC, Walter Bright wrote:I'm not really sure if this is an issue or not. I'll have to think about it. The visibility "attribute" is a bit of an oddity.Hence, no, you cannot use alias to modify the attributes.You can: public struct S { } private alias S S2; // visibility attribute is changed.Type modifiers: alias const(S) S2; // mutability attribute is changed.This is not a bug. const(S) is a type constructor, not an attribute, and you are aliasing a type, not a symbol.
Jan 04 2013
On 1/4/2013 8:04 AM, Philippe Sigaud wrote:So, I'm testing how to transfer UDA from one symbol to another.Remember, attributes are attached to the declaration. They are not transferred through initializers. This will do the transfer: import std.stdio; void main() { (3, "hello") int i = 10; (__traits(getAttributes, i)) double d2; writeln("[",__traits(getAttributes, d2), "]"); }
Jan 04 2013
On 1/4/13 3:51 PM, Walter Bright wrote:On 1/4/2013 8:04 AM, Philippe Sigaud wrote:For transfer templates are better than attributes. AndreiSo, I'm testing how to transfer UDA from one symbol to another.Remember, attributes are attached to the declaration. They are not transferred through initializers. This will do the transfer: import std.stdio; void main() { (3, "hello") int i = 10; (__traits(getAttributes, i)) double d2; writeln("[",__traits(getAttributes, d2), "]"); }
Jan 04 2013
On 1/4/2013 12:59 PM, Andrei Alexandrescu wrote:For transfer templates are better than attributes.Sure, but I wanted to illustrate what was happening. Templates tend to obscure things.
Jan 04 2013
On Fri, Jan 4, 2013 at 9:59 PM, Andrei Alexandrescu < SeeWebsiteForEmail erdani.org> wrote:On 1/4/13 3:51 PM, Walter Bright wrote:So, I'm testing how to transfer UDA from one symbol to another.Yes, I know. I just want to automate the process. I want a function or some piece of code that can propagate attributes. For example, say I receive a piece of unvalidated input. I test it and it's OK. I want to return it, with a new attribute (say, Validated() ),while keeping the input attributes. Since it seems a common need, I was looking for a way to abstract the process somewhat. For now, we would return a Validated(initialValue) struct. I just want to see how attributes can be used here. It seems that: (Validated, __traits(getAttributes, input)) InputType temp; return temp; do not work. If attribute manipulation cannot be isolated in easily reusable code, that would be sad. Andrei:This will do the transfer: import std.stdio; void main() { (3, "hello") int i = 10; (__traits(getAttributes, i)) double d2; writeln("[",__traits(**getAttributes, d2), "]"); }For transfer templates are better than attributes.Could you please give an example?
Jan 04 2013
On Friday, 4 January 2013 at 15:45:21 UTC, Philippe Sigaud wrote:OK, now that 2.061 is out, we have User-Defined Attributes (UDAs). Except, there is no doc on them, no explanation, nothing. For people who did not follow the monstrous threads in November, it's as if UDA do not exist....Here is the executive summary: 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.This is sorta like tuples; But from the brief summaries I cannot fully understand how or where they would be used. I understand some attributes can be made and added that some compilers may use ( noreturn as an example), but outside of the compiler I'd need an example of how to make use of them. Since there's no runtime component, then aside from carrying a tuple and some information forward at compile-time, what else can it do? How would you use it? Are there any special tuple formats that give information to automatically be included/compiled into the structs/classes without having to resort to mixins? Curiously enough it seems like clone would be a useful example. Let's assume we want to write clone, it's meaning that rather than writing a custom postblit to it's done automatically. struct S { string identifier; int value; string[] attributes; // clone this(this) {attributes = attributes.dup;} } Normally you'd write a this(this) as above, but if we used UDA's how could it be used/implemented?
Jan 04 2013
On 2013-01-04 21:33, Era Scarecrow wrote:This is sorta like tuples; But from the brief summaries I cannot fully understand how or where they would be used. I understand some attributes can be made and added that some compilers may use ( noreturn as an example), but outside of the compiler I'd need an example of how to make use of them. Since there's no runtime component, then aside from carrying a tuple and some information forward at compile-time, what else can it do? How would you use it? Are there any special tuple formats that give information to automatically be included/compiled into the structs/classes without having to resort to mixins?It could be used for serialization, for example. Have a look at my serialization library, Orange. http://dl.dropbox.com/u/18386187/orange_docs/orange.serialization.Serializable.html Look at the "NonSerialized" template, that could now be replaced by a UDA. Like this: class Foo { int a; NonSerialized int b; // will not be (de)serialized } -- /Jacob Carlborg
Jan 04 2013
Am Fri, 04 Jan 2013 21:33:03 +0100 schrieb "Era Scarecrow" <rtcvb32 yahoo.com>:On Friday, 4 January 2013 at 15:45:21 UTC, Philippe Sigaud wrote:One example is std.benchmark. It currently detects if a function is a benchmark function by checking the name: void benchmark_stdio(); With UDAs we can do this: benchmark stdio(); or benchmark("Benchmarking stdio reads, using xKB buffer") benchStdio1(); There's still the issue of "How do I get all the declarations in a module (/ the applications)", but UDAs already help a lot.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.This is sorta like tuples; But from the brief summaries I cannot fully understand how or where they would be used. I understand some attributes can be made and added that some compilers may use ( noreturn as an example), but outside of the compiler I'd need an example of how to make use of them.
Jan 05 2013
Clojure uses its metadata (attached to values, though, not declaration) to put documentation strings there. That's quite doable with D: (doc("This function does.... ")) auto foo() { ... } I'm also interested in tagging data: (Sorted!(withThisFun)) someRange ... (Ranged(0.0, 1.0)) someRange ... or: Validated SQLQuery query;
Jan 05 2013
On 2013-01-05 15:13, Philippe Sigaud wrote:Clojure uses its metadata (attached to values, though, not declaration) to put documentation strings there. That's quite doable with D: (doc("This function does.... ")) auto foo() { ... } I'm also interested in tagging data: (Sorted!(withThisFun)) someRange ... (Ranged(0.0, 1.0)) someRange ...Just for the record, the extra parentheses are not needed: doc("This function does.... ") auto foo () { } Sorted!(withThisFun) someRange ... -- /Jacob Carlborg
Jan 05 2013
On Sat, Jan 5, 2013 at 6:00 PM, Jacob Carlborg <doob me.com> wrote:Just for the record, the extra parentheses are not needed: doc("This function does.... ") auto foo () { } Sorted!(withThisFun) someRange ...Good to know. I tested it with basic values and this fails: "hello" int i; 3 inj j; Worth a bug report? As a complement, multiple 's are possible: ("hello") (3) int j; And another complement: struct S {} S S s; is possible. But int S s; is not So user-defined types are OK, but not basic types. Looks like a parsing/grammar problem for me, since attribute tuple sure should be able to store built-in types. Another bug report?
Jan 05 2013
On 2013-01-05 19:54, Philippe Sigaud wrote:Good to know. I tested it with basic values and this fails: "hello" int i; 3 inj j; Worth a bug report?No, that's by design. When I added that syntax first but I was asked to change it to only accept call expressions. Have a look at the grammar: https://dl.dropbox.com/u/18386187/attribute.html#udaAs a complement, multiple 's are possible: ("hello") (3) int j;Yes, that's legal and is supposed to be. Have a look at Walters original announcement: http://forum.dlang.org/thread/k7afq6$2832$1 digitalmars.com enum EEE = 7; ["hello"] struct SSS { } [3] { [4][EEE][SSS] int foo; } With the correct syntax that becomes: enum EEE = 7; ("hello") struct SSS { } (3) { (4) (EEE) (SSS) int foo; } Or: (3) { (4) EEE SSS int foo; }And another complement: struct S {} S S s; is possible. But int S s; is notThat is not supposed to be legal (see above), but this might be: (int) S s; Does that work?So user-defined types are OK, but not basic types. Looks like a parsing/grammar problem for me, since attribute tuple sure should be able to store built-in types. Another bug report?I'm not sure. -- /Jacob Carlborg
Jan 05 2013
No, that's by design. When I added that syntax first but I was asked to change it to only accept call expressions.No. It produces reams of error.int S s; is notThat is not supposed to be legal (see above), but this might be: (int) S s; Does that work?So user-defined types are OK, but not basic types. Looks like aI find it strange that MyType ... is OK, but not 3, when, at the same time (MyType) and (3) are *both* OK. Also, why is ("hello") and (SomeType) authorized, but not (int)? One extreme or the other looks OK for me: either only user-defined types are authorized (no int, no 3) or everything a tuple can hold is authorized (hence, int). The latter is more in line with the D way. Also, if parenthesis can be dropped, allow them to be dropped for anything that's a token long, as is done for template arguments. That seems coherent with the rest of the language.parsing/grammar problem for me, since attribute tuple sure should be able to store built-in types. Another bug report?I'm not sure.
Jan 05 2013
On 1/5/2013 10:54 AM, Philippe Sigaud wrote:Another bug report?This is as designed, not a bug. The attribute must start with a ( or identifier. Not keyword, number, string, operator, etc. If you want, file an enhancement request for more. But the design was deliberately restrictive for now.
Jan 05 2013
On Sat, Jan 5, 2013 at 10:20 PM, Walter Bright <newshound2 digitalmars.com>wrote:On 1/5/2013 10:54 AM, Philippe Sigaud wrote:That, I can understand. But why is (MyType) accepted, whereas (int) is not?Another bug report?This is as designed, not a bug. The attribute must start with a ( or identifier. Not keyword, number, string, operator, etc.
Jan 05 2013
On 1/5/2013 2:06 PM, Philippe Sigaud wrote:But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 05 2013
On Sat, Jan 5, 2013 at 11:14 PM, Walter Bright <newshound2 digitalmars.com>wrote:On 1/5/2013 2:06 PM, Philippe Sigaud wrote:Well, first that would be nice to have the grammar online :) Even if I understand the grammar restriction, from a user PoV this is quite unexpected: a built-in type is a completely legal part of a D tuple. Either it should be restricted to user-defined types (something I don't like), or, if attributes are supposed to be tuples, then any tuple element should be authorized. And I will not buy a possible argument saying that I can wrap an int inside a user-defined type. Yes, I can. But then, there is the same solution for (3) or ("Hello") and *these* are legal.But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 05 2013
On 2013-01-05 23:44, Philippe Sigaud wrote:Well, first that would be nice to have the grammar online :)Yeah, still waiting for that pull request to be merged. -- /Jacob Carlborg
Jan 05 2013
On Saturday, 5 January 2013 at 22:57:03 UTC, Jacob Carlborg wrote:On 2013-01-05 23:44, Philippe Sigaud wrote:UDA can not apply to function argument? enum attr; void func( attr int a) // <-- error { attr int b; // <-- ok }Well, first that would be nice to have the grammar online :)Yeah, still waiting for that pull request to be merged.
Jan 05 2013
On 1/5/2013 10:57 PM, Domain wrote:On Saturday, 5 January 2013 at 22:57:03 UTC, Jacob Carlborg wrote:Currently, no.On 2013-01-05 23:44, Philippe Sigaud wrote:UDA can not apply to function argument? enum attr; void func( attr int a) // <-- error { attr int b; // <-- ok }Well, first that would be nice to have the grammar online :)Yeah, still waiting for that pull request to be merged.
Jan 05 2013
On Sun, Jan 6, 2013 at 8:16 AM, Walter Bright <newshound2 digitalmars.com>wrote:Walter, what is the official way to return an attributed value? XXX? foo() { Marked int i; return i; }UDA can not apply to function argument?Currently, no.
Jan 06 2013
On 1/6/2013 1:48 AM, Philippe Sigaud wrote:Walter, what is the official way to return an attributed value? XXX? foo() { Marked int i; return i; }Values do not have attributes. Attributes are attached to symbols - not values or types.
Jan 06 2013
On 2013-01-06 10:48, Philippe Sigaud wrote:Walter, what is the official way to return an attributed value? XXX? foo() { Marked int i; return i; }Don't know if this is what you want but: struct Marked {} struct Attrs (T...) {} auto bar () { Marked int i; return Attrs!(__traits(getAttributes, i))(); } void main () { writeln(bar()); // prints Attrs!(Marked)() } -- /Jacob Carlborg
Jan 06 2013
Don't know if this is what you want but: struct Marked {} struct Attrs (T...) {} auto bar () { Marked int i; return Attrs!(__traits(getAttributes, i))(); } void main () { writeln(bar()); // prints Attrs!(Marked)() }I just want to be able to return an attributed something. How can a function return something that's attributed? IIUC what Walter said, a function cannot return an attributed value: any internal symbol can be attributed, but these cannot get out. I can create can attributed value to 'catch' what a function returns, but not automatically: ??? attributedInt() { ("Hello") int i = 1; return i; } void main() { ??? j = attributedInt(); // How to have j get the ("Hello") attribute? } The only way would be what you suggest: - extract the attributes from the internal i - store them in a specially-crafted struct - return that - in the external code, catch the returned struct - extract the artificially stored attributes - generate a new value with the same attributes. Ugh.
Jan 06 2013
On 2013-01-06 14:29, Philippe Sigaud wrote:I just want to be able to return an attributed something. How can a function return something that's attributed? IIUC what Walter said, a function cannot return an attributed value: any internal symbol can be attributed, but these cannot get out. I can create can attributed value to 'catch' what a function returns, but not automatically: ??? attributedInt() { ("Hello") int i = 1; return i; } void main() { ??? j = attributedInt(); // How to have j get the ("Hello") attribute? } The only way would be what you suggest: - extract the attributes from the internal i - store them in a specially-crafted struct - return that - in the external code, catch the returned struct - extract the artificially stored attributes - generate a new value with the same attributes.Basically, yes. I haven't been able figured out something else. -- /Jacob Carlborg
Jan 06 2013
On 2013-01-06 14:29, Philippe Sigaud wrote:Don't know if this is what you want but: struct Marked {} struct Attrs (T...) {} auto bar () { Marked int i; return Attrs!(__traits(getAttributes, i))(); } void main () { writeln(bar()); // prints Attrs!(Marked)() } I just want to be able to return an attributed something. How can a function return something that's attributed? IIUC what Walter said, a function cannot return an attributed value: any internal symbol can be attributed, but these cannot get out. I can create can attributed value to 'catch' what a function returns, but not automatically: ??? attributedInt() { ("Hello") int i = 1; return i; } void main() { ??? j = attributedInt(); // How to have j get the ("Hello") attribute? } The only way would be what you suggest: - extract the attributes from the internal i - store them in a specially-crafted struct - return that - in the external code, catch the returned struct - extract the artificially stored attributes - generate a new value with the same attributes.You can perhaps encapsulate this in a mixin? -- /Jacob Carlborg
Jan 06 2013
The only way would be what you suggest:That would mean two mixins, one internal and one external. Plus, that means every function where I want to propagate UDA has to be crafted exactly for this need. This is a drag. It seems natural to me that int foo(int i) { return i;} should forward i attributes. But maybe I need a shift my way to think about attributes. They are attached to declarations, not values... That's too bad, because declaring UDA is simple, and receiving them with arguments is easy also. There is a fundamental imbalance in having having propagating attributes through functions so difficult.- extract the attributes from the internal i - store them in a specially-crafted struct - return that - in the external code, catch the returned struct - extract the artificially stored attributes - generate a new value with the same attributes.You can perhaps encapsulate this in a mixin?
Jan 06 2013
On 2013-01-06 15:25, Philippe Sigaud wrote:That would mean two mixins, one internal and one external. Plus, that means every function where I want to propagate UDA has to be crafted exactly for this need. This is a drag. It seems natural to me that int foo(int i) { return i;} should forward i attributes. But maybe I need a shift my way to think about attributes. They are attached to declarations, not values...Exactly.That's too bad, because declaring UDA is simple, and receiving them with arguments is easy also. There is a fundamental imbalance in having having propagating attributes through functions so difficult.Yeah, if you want to work with UDA's you need to work with symbols, not values or types. If you want to pass a symbol, including its UDA, you need to pass it as an alias: void foo (alias symbol) () { // access UDA of symbol } (3) int a; foo!(a); -- /Jacob Carlborg
Jan 06 2013
On Sun, Jan 6, 2013 at 3:29 PM, Jacob Carlborg <doob me.com> wrote:Yeah, if you want to work with UDA's you need to work with symbols, not values or types. If you want to pass a symbol, including its UDA, you need to pass it as an alias:That was the explanation I needed: UDA are attached to symbols. Now that's, clearer ;) Hmm, did anyone try to put attribute before a function overload and not another? Ca (PS: symbols, except modules, because they are second-class citizens)
Jan 06 2013
Hmm, did anyone try to put attribute before a function overload and notanother?CaDamn tab. Can attributes be defined by templates arguments? (T) class C(T) : T { } Answer: no. OK.
Jan 06 2013
On 01/06/2013 07:24 PM, Philippe Sigaud wrote:Can attributes be defined by templates arguments? (T) class C(T) : T { } Answer: no. OK.This works: template C(T){ T class C : T { } } The above appears to annotate the template itself, which is inconsistent. You should probably file a bug report.
Jan 06 2013
On 1/6/13 9:25 AM, Philippe Sigaud wrote:That's too bad, because declaring UDA is simple, and receiving them with arguments is easy also. There is a fundamental imbalance in having having propagating attributes through functions so difficult.<brokenrecord>For designing attributes that navigate with types templates would be the solution of choice.</brokenrecord> Andrei
Jan 06 2013
Andrei Alexandrescu:<brokenrecord>For designing attributes that navigate with types templates would be the solution of choice.</brokenrecord>There's an interesting cognitive impercetion phenomena here, that's worth studying and not ignoring. From the little evidence here, it seems that D programmers want to use UDAs instead of templates for those purposes. Possibly because UDAs look more fit (despite you rightfully say they aren't). Bye, bearophile
Jan 06 2013
On Sun, Jan 6, 2013 at 3:58 PM, Andrei Alexandrescu < SeeWebsiteForEmail erdani.org> wrote:On 1/6/13 9:25 AM, Philippe Sigaud wrote:Care to show a small example? I tried 1-2 years ago. With alias this, that's partially acceptable. I just remember it was a bit burdensome tp use and dumped it. But OK, if UDA do not do that, then I'll go back to templates. Since alias this become better, maybe something can be done here.That's too bad, because declaring UDA is simple, and receiving them with arguments is easy also. There is a fundamental imbalance in having having propagating attributes through functions so difficult.<brokenrecord>For designing attributes that navigate with types templates would be the solution of choice.</brokenrecord>
Jan 06 2013
On Sunday, 6 January 2013 at 14:58:07 UTC, Andrei Alexandrescu wrote:On 1/6/13 9:25 AM, Philippe Sigaud wrote:Isn't it better to achieve this with a template ?That's too bad, because declaring UDA is simple, and receiving them with arguments is easy also. There is a fundamental imbalance in having having propagating attributes through functions so difficult.<brokenrecord>For designing attributes that navigate with types templates would be the solution of choice.</brokenrecord> Andrei
Jan 06 2013
On 01/06/2013 11:27 PM, deadalnix wrote:On Sunday, 6 January 2013 at 14:58:07 UTC, Andrei Alexandrescu wrote:No, it is equivalent.On 1/6/13 9:25 AM, Philippe Sigaud wrote:Isn't it better to achieve this with a template ?That's too bad, because declaring UDA is simple, and receiving them with arguments is easy also. There is a fundamental imbalance in having having propagating attributes through functions so difficult.<brokenrecord>For designing attributes that navigate with types templates would be the solution of choice.</brokenrecord> Andrei
Jan 06 2013
On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On Sun, Jan 6, 2013 at 11:24 PM, deadalnix <deadalnix gmail.com> wrote:On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:Same thought here.On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On 01/06/2013 11:24 PM, deadalnix wrote:On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:Sure! ... struct IdentifierExp : Expression { Identifier *ident; Declaration *var; ...On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On 1/6/2013 2:24 PM, deadalnix wrote:On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:Parsing happens before semantic analysis. Hence, MyType looks like an expression.On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On Monday, 7 January 2013 at 00:38:35 UTC, Walter Bright wrote:On 1/6/2013 2:24 PM, deadalnix wrote:OK, but if int is invalid, should semantic analysis reject MyType as well ?On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:Parsing happens before semantic analysis. Hence, MyType looks like an expression.On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On 1/6/2013 5:06 PM, deadalnix wrote:On Monday, 7 January 2013 at 00:38:35 UTC, Walter Bright wrote:Tuples accept both types and expressions, and the semantic analyzer loads it into the tuple.On 1/6/2013 2:24 PM, deadalnix wrote:OK, but if int is invalid, should semantic analysis reject MyType as well ?On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:Parsing happens before semantic analysis. Hence, MyType looks like an expression.On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On 01/07/2013 01:38 AM, Walter Bright wrote:On 1/6/2013 2:24 PM, deadalnix wrote:Sure, that is how the compiler currently works. The compiler is an inadequate reference at this point. (Eg. I am still reducing the massive breakage introduced by 2.061 regressions. Mostly 'forward reference' errors -- mentioned nowhere in the spec, and seemingly introduced in order to 'fix' ICEs.) Why does it make sense from the standpoint of language design? The compiler should obviously use the part of the parser that parses template arguments to parse UDA's. I am surprised this is not what is done. Also, this particular problem would not exist in the first place if basic types just were treated like expressions in the parser. I am not familiar with DMD, but I bet the special casing of built-ins leaves an ugly trail in the code base.On Saturday, 5 January 2013 at 22:14:47 UTC, Walter Bright wrote:Parsing happens before semantic analysis. Hence, MyType looks like an expression.On 1/5/2013 2:06 PM, Philippe Sigaud wrote:And mytype is an expression ?????But why is (MyType) accepted, whereas (int) is not?Because it's looking for an expression inside the parents, and int is not an expression.
Jan 06 2013
On 01/07/2013 04:27 AM, Timon Gehr wrote:... (Eg. I am still reducing the massive breakage introduced by 2.061 regressions. Mostly 'forward reference' errors -- mentioned nowhere in the spec, and seemingly introduced in order to 'fix' ICEs.) ...dustmite ftw. http://d.puremagic.com/issues/show_bug.cgi?id=9276
Jan 06 2013
On 1/6/2013 8:37 PM, Timon Gehr wrote:dustmite ftw. http://d.puremagic.com/issues/show_bug.cgi?id=9276Thank you.
Jan 06 2013
On Mon, Jan 7, 2013 at 4:27 AM, Timon Gehr <timon.gehr gmx.ch> wrote:The compiler should obviously use the part of the parser that parses template arguments to parse UDA's. I am surprised this is not what is done.I humbly concur. Walter, you yourself presented UDAs as 'linking the dots' between different part of the D language (tuples...). It's an interesting and elegant approach, but the current situation is somewhat inadequate: UDA can be manipulated like template tuple parameters and should be parsed as such.
Jan 06 2013
On 1/6/2013 9:44 PM, Philippe Sigaud wrote:I humbly concur. Walter, you yourself presented UDAs as 'linking the dots' between different part of the D language (tuples...). It's an interesting and elegant approach, but the current situation is somewhat inadequate: UDA can be manipulated like template tuple parameters and should be parsed as such.Well, I am glad to see people using it.
Jan 06 2013
On 1/6/2013 7:27 PM, Timon Gehr wrote:I am still reducing the massive breakage introduced by 2.061 regressions.Sorry about that, but 2.061 has been available for 2 months in beta. We fixed all but 3 of the reported regressions, and had good reasons for deferring those. In fact, the 2.062 work in progress release is currently up on the site.
Jan 06 2013
On 01/07/2013 07:27 AM, Walter Bright wrote:On 1/6/2013 7:27 PM, Timon Gehr wrote:No problem. There will be some way to get it to compile. The reduced code shows which points to concentrate modification on. I have quite a few workarounds for forward reference errors in my code already.I am still reducing the massive breakage introduced by 2.061 regressions.Sorry about that,but 2.061 has been available for 2 months in beta.I think this is a valid point, but coincidentally, I have not been working on the code base for the past 2 months.We fixed all but 3 of the reported regressions, and had good reasons for deferring those.I am sure that very good progress is being made. However, the forward reference error problem will need formal treatment at some point. I think one reason they pop up is that symbol lookup for the intended language is inherently impossible to compute.In fact, the 2.062 work in progress release is currently up on the site.Great! The remark was not intended as a critique of DMD's development process, rather I was attempting to support the point that for language design issues, implementation details are of secondary importance.
Jan 06 2013
On 1/6/2013 11:31 PM, Timon Gehr wrote:I am sure that very good progress is being made. However, the forward reference error problem will need formal treatment at some point. I think one reason they pop up is that symbol lookup for the intended language is inherently impossible to compute.A huge source of fwd ref problems was not at all about symbol lookup. It was about partial types referencing properties of themselves. For example, struct S { int a; int b = S.sizeof; int c; } for a simple example. There've been all kinds of variations on this theme, some of them wickedly complicated, but always boiling down to the same general issue. Some forward ref regressions have cropped up because the compiler now does a better job of checking if there is enough of the type computed to get the desired property. Formerly, it would just return an incorrect size (for example). (I do not know if this is the case for your example, yet.)
Jan 06 2013
On Monday, 7 January 2013 at 07:58:29 UTC, Walter Bright wrote:A huge source of fwd ref problems was not at all about symbol lookup. It was about partial types referencing properties of themselves. For example, struct S { int a; int b = S.sizeof; int c; } for a simple example. There've been all kinds of variations on this theme, some of them wickedly complicated, but always boiling down to the same general issue. Some forward ref regressions have cropped up because the compiler now does a better job of checking if there is enough of the type computed to get the desired property. Formerly, it would just return an incorrect size (for example). (I do not know if this is the case for your example, yet.)I've had certain headaches from that as well trying to make my polymorphic struct, it's easy to see how it can get lost. struct S { static struct Data { int i; } union { Data data; S2 s2; //problem line } } struct S2 { S base; //problem line } Here the whole size is defined by Data, however because S2 references S1 before it has a concrete size it can get stuck (may still get stuck, not sure). Hmmm in cases like this, a size attribute could be useful (forces it to believe given size rather than looking it up). So that could become: union { Data data; size(Data.sizeof) S2 s2; //size hint, forward ref problem gone }
Jan 07 2013
On Saturday, 5 January 2013 at 11:57:39 UTC, Johannes Pfau wrote:Era Scarecrow wrote:Yes I understand how you can attach some information using a UDA, but that still doesn't tell me _how to use_ it. Unless you can somehow locate & manipulate/use/pass the information around than it's no more than a comment that isn't removed immediately. Slightly off topic: I get the feeling that with the questions of current specs, the large number of changes (few hugely breaking) and outdated TDPL the language documentation needs a good through update. Perhaps a TDPL v2 regarding changes to the language; Rather than replacing TDPL, it instead it compliments it. And when phobos is more mature and isn't going to be changing then an API/reference book for it would likely be a third book.This is sorta like tuples; But from the brief summaries I cannot fully understand how or where they would be used. I understand some attributes can be made and added that some compilers may use ( noreturn as an example), but outside of the compiler I'd need an example of how to make use of them.One example is std.benchmark. It currently detects if a function is a benchmark function by checking the name: void benchmark_stdio(); With UDAs we can do this: benchmark stdio(); or benchmark("Benchmarking stdio reads, using xKB buffer") benchStdio1(); There's still the issue of "How do I get all the declarations in a module (/ the applications)", but UDAs already help a lot.
Jan 06 2013