digitalmars.D.learn - User defined attributes use
- matovitch (13/13) Sep 15 2013 Hi everyone,
- Jacob Carlborg (33/36) Sep 15 2013 I'm using it in my serialization library:
- simendsjo (28/42) Sep 15 2013 It enables declarative programming.
- ilya-stromberg (5/53) Sep 15 2013 Can you print a full examle? For example, can you implement
- simendsjo (62/123) Sep 16 2013 I don't have a full example without adding a lot of code, but
- matovitch (11/11) Sep 16 2013 All your examples are great, thank you ! Is there a way to omit
- Bienlein (4/15) Sep 16 2013 Very interesting. Does this go beyond annotations in Java? Just
- matovitch (5/24) Sep 16 2013 And with template parameters.
- Maxim Fomin (3/14) Sep 16 2013 No, this isn't doable with UDAs because what you want requires
- ilya-stromberg (5/23) Sep 16 2013 It's intresting how can I check that pointer is not null at the
- Namespace (3/28) Sep 16 2013 That isn't possible. ;)
- Maxim Fomin (40/71) Sep 16 2013 Similar effect can be achieved by different way. If some function
- ilya-stromberg (3/6) Sep 16 2013 Do you know why D structs don't have default constructors? I
- Namespace (6/12) Sep 16 2013 My favorites:
- Namespace (10/83) Sep 16 2013 Yes, I know. Search for my name and not null, you will find many
- H. S. Teoh (15/18) Sep 16 2013 [...]
- Namespace (7/31) Sep 16 2013 Built-in Arrays have also problems.
- Adam D. Ruppe (19/21) Sep 16 2013 It's worth pointing out that the library AAs proposed here would
- Namespace (4/15) Sep 16 2013 Then of course I have not said anything.
- Namespace (3/25) Sep 16 2013 And maybe also for delete: we need something to delete the memory
- ilya-stromberg (2/4) Sep 16 2013 And we need built-in memory allocators, not only GC.
- Jacob Carlborg (5/8) Sep 16 2013 I think the big difference here is that AA's are safe where "scope" is
- Artur Skawina (15/29) Sep 16 2013 Yes. Without any doubt whatsoever. [1]
- Namespace (2/12) Sep 16 2013 Why to high? Too much compiler magic or dmd internal dependences?
- H. S. Teoh (27/38) Sep 16 2013 I disagree that it's too high. It just needs *somebody* with the right
- Artur Skawina (6/13) Sep 16 2013 Too much (language) change for too little gain; there are many, many
- Artur Skawina (4/20) Sep 16 2013 I thought (s)he was asking about *arrays*, not AAs. There's no disagreem...
- Namespace (3/32) Sep 16 2013 Yes, he was. ;)
- H. S. Teoh (8/22) Sep 16 2013 [...]
- Jacob Carlborg (5/8) Sep 16 2013 I guess one can complain about some of the built-in
- Artur Skawina (38/58) Sep 17 2013 Not that much, at least not enough to worry about it right now,
- Maxim Fomin (28/52) Sep 16 2013 This demonstrates an interesting issue.
- Andrei Alexandrescu (9/17) Sep 16 2013 If we're diligent and lucky, hopefully.
- H. S. Teoh (20/33) Sep 16 2013 One thing I'd *really* like to have is proper escape analysis and
- ilya-stromberg (22/31) Sep 16 2013 Yes, we REALLY need this. I know that we can init struct fields
- Namespace (13/34) Sep 16 2013 Long time not heard from each other. ;)
- simendsjo (9/20) Sep 16 2013 As others have noted, the compiler cannot know what any of your
- ilya-stromberg (23/83) Sep 19 2013 Can I explicitly specify when I can use attribute? Something like
- Jacob Carlborg (11/33) Sep 20 2013 Unfortunately you can't. I tag all my structs which are supposed to be
- simendsjo (11/48) Sep 20 2013 You could of course fix this in a library too.
- Jacob Carlborg (4/13) Sep 23 2013 I'm not sure how I could do that.
- simendsjo (7/22) Sep 23 2013 You can recurse into UDAs for attributes and pass along the type
Hi everyone, I read the documentation about user defined attributes, but I don't see their uses. Ok, it'a a template expression you can link to a declaration, but what are they useful for ? (not sure about the syntax ;-)) Can you declare a template constraint as a user defined attribute to do something like : void template_function_which_go_back_and_forth( ("Bidirectional") ("Range") BR)(BR br) {...} This would be awesome (even if not really occidental) to do something like: ("SmallTypeSet") ("MediumTypeSet") ("LargeTypeSet") Type This could allow to build tree based category structure.
Sep 15 2013
On 2013-09-15 19:34, matovitch wrote:Hi everyone, I read the documentation about user defined attributes, but I don't see their uses.I'm using it in my serialization library: struct Foo { int a; nonSerialized int b; } Indicates "b" will not be serialized. struct Bar { int a; onSerializing void foo () { // called when "Bar" is being serialized } } "foo" will be called when "Bar" is being serialized For another project I'm using it as part of a testing framework: describe("Lexer") { context("valid string literal") { it("should return a token with the type TokenKind.stringLiteral") unittest { auto code = `"asd"`; auto lexer = new Lexer(code); assert(lexer.scan.kind == TokenKind.stringLiteral); } } } -- /Jacob Carlborg
Sep 15 2013
On Sunday, 15 September 2013 at 17:34:06 UTC, matovitch wrote:Hi everyone, I read the documentation about user defined attributes, but I don't see their uses. Ok, it'a a template expression you can link to a declaration, but what are they useful for ? (not sure about the syntax ;-)) Can you declare a template constraint as a user defined attribute to do something like : void template_function_which_go_back_and_forth( ("Bidirectional") ("Range") BR)(BR br) {...} This would be awesome (even if not really occidental) to do something like: ("SmallTypeSet") ("MediumTypeSet") ("LargeTypeSet") Type This could allow to build tree based category structure.It enables declarative programming. And because this is D, there is no runtime overhead. A common use is to add semantics to types and instances that is difficult or very intrusive to do by creating structs/classes by hand. A little validation example: nonNull // An instance shouldn't be allowed to be null class C { matches("[0-9]+") string someNumber; interval!"(]"(0, 10) // (0, 10] range int someInt; } C c; validate(c); // returns ["C is null", "someNumber doesn't match '[0-9]+'", "someInt is outside the interval '(0, 10]'"] And ORMs usually use annotations: table("some_tablename") class C { id("id_field_name") int id; } attributes/annotations - they are still quite new in D, so they are still underutilized. A very big difference is of course that UDAs are available at compile time :)
Sep 15 2013
On Sunday, 15 September 2013 at 18:31:40 UTC, simendsjo wrote:On Sunday, 15 September 2013 at 17:34:06 UTC, matovitch wrote:Can you print a full examle? For example, can you implement "matches" UDA and validate function. It's intresting how can I create new UDA and check if it's available for class/field.Hi everyone, I read the documentation about user defined attributes, but I don't see their uses. Ok, it'a a template expression you can link to a declaration, but what are they useful for ? (not sure about the syntax ;-)) Can you declare a template constraint as a user defined attribute to do something like : void template_function_which_go_back_and_forth( ("Bidirectional") ("Range") BR)(BR br) {...} This would be awesome (even if not really occidental) to do something like: ("SmallTypeSet") ("MediumTypeSet") ("LargeTypeSet") Type This could allow to build tree based category structure.It enables declarative programming. And because this is D, there is no runtime overhead. A common use is to add semantics to types and instances that is difficult or very intrusive to do by creating structs/classes by hand. A little validation example: nonNull // An instance shouldn't be allowed to be null class C { matches("[0-9]+") string someNumber; interval!"(]"(0, 10) // (0, 10] range int someInt; } C c; validate(c); // returns ["C is null", "someNumber doesn't match '[0-9]+'", "someInt is outside the interval '(0, 10]'"] And ORMs usually use annotations: table("some_tablename") class C { id("id_field_name") int id; } attributes/annotations - they are still quite new in D, so they are still underutilized. A very big difference is of course that UDAs are available at compile time :)
Sep 15 2013
On Monday, 16 September 2013 at 06:47:40 UTC, ilya-stromberg wrote:On Sunday, 15 September 2013 at 18:31:40 UTC, simendsjo wrote:I don't have a full example without adding a lot of code, but this partial example might give you the gist of it. // This is the type that validates struct matches(string mustMatch) { alias re = ctRegex!(mustMatch); static string[] validate(T)(const ref T t) { static if(!isSomeString!T) static assert(0, "matches only works on strings, not "~T.stringof); return match(t, re).empty ? ["no match"] : null; } } // and this is the code that runs all validators for a variable void validate(alias T)(ref Appender!(string[]) app) { static if(isTupleWrapper!T) { validate!(T.Head)(app); validate!(T.Tail)(app); } else { foreach(memberAttr; getValidaterAttrs!T) { foreach(attr; memberAttr.Tail) { foreach(msg; attr.validate(T)) if(msg.length) app.put(msg); } } } } // .. And here is some of the plumbing string[] validate(Vars...)() { auto app = appender!(string[])(); validate!Vars(app); return app.data(); } // The getMembersAndAttributesWhere are templates in my little library that isn't released. Uses quite some custom __traits stuff, but it's basically __traits(getAttributes template getValidaterAttrs(alias T) { alias getValidaterAttrs = TypeTuple!(getMembersAndAttributesWhere!(T, isValidationAttr).Elements, getMembersAndAttributesWhere!(TypeOf!T, isValidationAttr).Elements); } // Well.. Incomplete template isValidationAttr(alias T) { enum isValidationAttr = hasMember!(TypeOf!T, "validate"); }On Sunday, 15 September 2013 at 17:34:06 UTC, matovitch wrote:Can you print a full examle? For example, can you implement "matches" UDA and validate function. It's intresting how can I create new UDA and check if it's available for class/field.Hi everyone, I read the documentation about user defined attributes, but I don't see their uses. Ok, it'a a template expression you can link to a declaration, but what are they useful for ? (not sure about the syntax ;-)) Can you declare a template constraint as a user defined attribute to do something like : void template_function_which_go_back_and_forth( ("Bidirectional") ("Range") BR)(BR br) {...} This would be awesome (even if not really occidental) to do something like: ("SmallTypeSet") ("MediumTypeSet") ("LargeTypeSet") Type This could allow to build tree based category structure.It enables declarative programming. And because this is D, there is no runtime overhead. A common use is to add semantics to types and instances that is difficult or very intrusive to do by creating structs/classes by hand. A little validation example: nonNull // An instance shouldn't be allowed to be null class C { matches("[0-9]+") string someNumber; interval!"(]"(0, 10) // (0, 10] range int someInt; } C c; validate(c); // returns ["C is null", "someNumber doesn't match '[0-9]+'", "someInt is outside the interval '(0, 10]'"] And ORMs usually use annotations: table("some_tablename") class C { id("id_field_name") int id; } attributes/annotations - they are still quite new in D, so they are still underutilized. A very big difference is of course that UDAs are available at compile time :)
Sep 16 2013
All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is null
Sep 16 2013
On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullVery interesting. Does this go beyond annotations in Java? Just out of curiosity, no language war intended. -- Bienlein
Sep 16 2013
On Monday, 16 September 2013 at 10:36:16 UTC, Bienlein wrote:On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:And with template parameters. fun( Arithmetic T)(...) {...} alias fun!string funstr; //compilation error since a string is not an arithmetic typeAll your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullVery interesting. Does this go beyond annotations in Java? Just out of curiosity, no language war intended. -- Bienlein
Sep 16 2013
On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullNo, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features.
Sep 16 2013
On Monday, 16 September 2013 at 15:12:05 UTC, Maxim Fomin wrote:On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:It's intresting how can I check that pointer is not null at the compile time. Can you print a example, please? I know that we can use contract programming, but it requires runtime check.All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullNo, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features.
Sep 16 2013
On Monday, 16 September 2013 at 15:47:36 UTC, ilya-stromberg wrote:On Monday, 16 September 2013 at 15:12:05 UTC, Maxim Fomin wrote:That isn't possible. ;)On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:It's intresting how can I check that pointer is not null at the compile time. Can you print a example, please? I know that we can use contract programming, but it requires runtime check.All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullNo, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features.
Sep 16 2013
On Monday, 16 September 2013 at 16:50:43 UTC, Namespace wrote:On Monday, 16 September 2013 at 15:47:36 UTC, ilya-stromberg wrote:Similar effect can be achieved by different way. If some function takes S as parameter, one cannot pass directly instance of A or null - error will be issued which is some sort of compile-time protection. class A { int i; } struct S { A a; A getA() { if (a is null) a = new A; return a; } alias getA this; } void main() { S s; assert (s.i is 0); S ss = S.init; assert (ss.i is 0); } Unfortunately D does not have non-nullable classes which is a initialize class instance. Since they are absent, wrapping struct can be enhanced by inserting disabled constructor to ensure that no default struct instances with null references are created. However, since disabled constructors are also flawed (they don't prevent from producing T.init values by design and in some situations dmd is not smart enough to detect other cases by by code above using alias this + rt check. At least this works with two most problematic cases of struct initilialization: without initializer and with T.init value.On Monday, 16 September 2013 at 15:12:05 UTC, Maxim Fomin wrote:That isn't possible. ;)On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:It's intresting how can I check that pointer is not null at the compile time. Can you print a example, please? I know that we can use contract programming, but it requires runtime check.All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullNo, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features.
Sep 16 2013
On Monday, 16 September 2013 at 17:50:16 UTC, Maxim Fomin wrote:Ideally structs should have default constructors (hello to instance.Do you know why D structs don't have default constructors? I really miss.
Sep 16 2013
On Monday, 16 September 2013 at 18:44:25 UTC, ilya-stromberg wrote:On Monday, 16 September 2013 at 17:50:16 UTC, Maxim Fomin wrote:My favorites: http://forum.dlang.org/thread/ij6kl4$2jv9$1 digitalmars.com http://forum.dlang.org/thread/bvuquzwfykiytdwsqkky forum.dlang.org http://forum.dlang.org/thread/icjwbtlxsaekksyoljfp forum.dlang.orgIdeally structs should have default constructors (hello to instance.Do you know why D structs don't have default constructors? I really miss.
Sep 16 2013
On Monday, 16 September 2013 at 17:50:16 UTC, Maxim Fomin wrote:On Monday, 16 September 2013 at 16:50:43 UTC, Namespace wrote:Yes, I know. Search for my name and not null, you will find many topics. I hate this NotNull struct hack. It is the same crap as the current scope solution. BTW: I'm curious which built-in feature will be removed next, maybe AA? An annotation like Foo! f would be much nicer than NotNull!Foo or NotNull Foo, but it would be an agreement. And I agree absolute, to disable default CTor's by struct's was a huge mistake. But D is full of those. ;)On Monday, 16 September 2013 at 15:47:36 UTC, ilya-stromberg wrote:Similar effect can be achieved by different way. If some function takes S as parameter, one cannot pass directly instance of A or null - error will be issued which is some sort of compile-time protection. class A { int i; } struct S { A a; A getA() { if (a is null) a = new A; return a; } alias getA this; } void main() { S s; assert (s.i is 0); S ss = S.init; assert (ss.i is 0); } Unfortunately D does not have non-nullable classes which is a initialize class instance. Since they are absent, wrapping struct can be enhanced by inserting disabled constructor to ensure that no default struct instances with null references are created. However, since disabled constructors are also flawed (they don't prevent from producing T.init values by design and in some situations dmd is not smart enough to detect can be simulated by code above using alias this + rt check. At least this works with two most problematic cases of struct initilialization: without initializer and with T.init value.On Monday, 16 September 2013 at 15:12:05 UTC, Maxim Fomin wrote:That isn't possible. ;)On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:It's intresting how can I check that pointer is not null at the compile time. Can you print a example, please? I know that we can use contract programming, but it requires runtime check.All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullNo, this isn't doable with UDAs because what you want requires runtime check. It is doable using other language features.
Sep 16 2013
On Mon, Sep 16, 2013 at 08:56:17PM +0200, Namespace wrote: [...]I hate this NotNull struct hack. It is the same crap as the current scope solution. BTW: I'm curious which built-in feature will be removed next, maybe AA?[...] That wouldn't be a bad idea, actually. The current AA implementation is so horribly broken, and so wrong in so many ways (there are at least 75 bugs related to AA's, some of the worst of which are 11037, 11025, 10916, 10525, 10381, 10380, 10046, just to name a few), that it would do a world of good to get rid of them altogether, and then reintroduce a properly-designed library solution for them. Of course, in the meantime everyone whose code breaks because of that will form a mob to lynch me, so I'll have to survive long enough to get the library solution working first. :-P T -- Microsoft is to operating systems & security ... what McDonalds is to gourmet cooking.
Sep 16 2013
On Monday, 16 September 2013 at 19:21:47 UTC, H. S. Teoh wrote:On Mon, Sep 16, 2013 at 08:56:17PM +0200, Namespace wrote: [...]Built-in Arrays have also problems. What should we do? Remove and rewrite them also as library solution? With Arrays and AA's we would lose a lot of good differences to C++. Why should anyone switch to D if it is nothing else as a new C++?I hate this NotNull struct hack. It is the same crap as the current scope solution. BTW: I'm curious which built-in feature will be removed next, maybe AA?[...] That wouldn't be a bad idea, actually. The current AA implementation is so horribly broken, and so wrong in so many ways (there are at least 75 bugs related to AA's, some of the worst of which are 11037, 11025, 10916, 10525, 10381, 10380, 10046, just to name a few), that it would do a world of good to get rid of them altogether, and then reintroduce a properly-designed library solution for them. Of course, in the meantime everyone whose code breaks because of that will form a mob to lynch me, so I'll have to survive long enough to get the library solution working first. :-P T
Sep 16 2013
On Monday, 16 September 2013 at 19:58:51 UTC, Namespace wrote:Why should anyone switch to D if it is nothing else as a new C++?It's worth pointing out that the library AAs proposed here would still have the same syntax as the built-in ones now. int[string] a; would just be magically rewritten into AssociativeArray!(int, string) a; and ["one" : 1, "two" : 2], would just become something like AALiteral(["one", "two"], [1, 2]);, or whatever, I'm not sure exactly what they were going to do there. Anyway though, all the sugar is still there, just a new implementation as a regular D struct instead of a bunch of calls to _d_assocarray and the other dozen magic functions and typeinfo things it uses now. BTW part of the bugginess is because this move to the library was half-assed. It does do the AssocativeArray rewrite... but it also still uses the magic functions. So there's all kinds of weird crap going on that can make programs fail to link and other bugs since we've been stuck in this no-man's land for years.
Sep 16 2013
On Monday, 16 September 2013 at 20:09:53 UTC, Adam D. Ruppe wrote:On Monday, 16 September 2013 at 19:58:51 UTC, Namespace wrote:Then of course I have not said anything. The same thing I would suggest for scope. It exists as a library solution and is rewritten magical.Why should anyone switch to D if it is nothing else as a new C++?It's worth pointing out that the library AAs proposed here would still have the same syntax as the built-in ones now. int[string] a; would just be magically rewritten into AssociativeArray!(int, string) a; and ["one" : 1, "two" : 2], would just become something like AALiteral(["one", "two"], [1, 2]);, or whatever, I'm not sure exactly what they were going to do there.
Sep 16 2013
On Monday, 16 September 2013 at 20:15:26 UTC, Namespace wrote:On Monday, 16 September 2013 at 20:09:53 UTC, Adam D. Ruppe wrote:And maybe also for delete: we need something to delete the memory manually.On Monday, 16 September 2013 at 19:58:51 UTC, Namespace wrote:Then of course I have not said anything. The same thing I would suggest for scope. It exists as a library solution and is rewritten magical.Why should anyone switch to D if it is nothing else as a new C++?It's worth pointing out that the library AAs proposed here would still have the same syntax as the built-in ones now. int[string] a; would just be magically rewritten into AssociativeArray!(int, string) a; and ["one" : 1, "two" : 2], would just become something like AALiteral(["one", "two"], [1, 2]);, or whatever, I'm not sure exactly what they were going to do there.
Sep 16 2013
On Monday, 16 September 2013 at 20:16:45 UTC, Namespace wrote:And maybe also for delete: we need something to delete the memory manually.And we need built-in memory allocators, not only GC.
Sep 16 2013
On 2013-09-16 22:15, Namespace wrote:Then of course I have not said anything. The same thing I would suggest for scope. It exists as a library solution and is rewritten magical.I think the big difference here is that AA's are safe where "scope" is not. I agree with you, I like to use "scope" anyway. -- /Jacob Carlborg
Sep 16 2013
On 09/16/13 21:58, Namespace wrote:On Monday, 16 September 2013 at 19:21:47 UTC, H. S. Teoh wrote:[...]On Mon, Sep 16, 2013 at 08:56:17PM +0200, Namespace wrote: [...]I hate this NotNull struct hack. It is the same crap as the current scope solution. BTW: I'm curious which built-in feature will be removed next, maybe AA?[...] That wouldn't be a bad idea, actually. The current AA implementation is so horribly broken, and so wrong in so many ways (there are at least 75Built-in Arrays have also problems. What should we do? Remove and rewrite them also as library solution?Yes. Without any doubt whatsoever. [1]With Arrays and AA's we would lose a lot of good differences to C++.Removing hardwired builtin magic does not imply syntax changes. And, the syntax that matters in practice is not the declarations, but the literals, which is where the language could do much better anyway.Why should anyone switch to D if it is nothing else as a new C++?D is not only about arrays. artur [1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.
Sep 16 2013
D is not only about arrays.It's a big plus. ;)[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 16 2013
On Mon, Sep 16, 2013 at 10:38:58PM +0200, Namespace wrote:I disagree that it's too high. It just needs *somebody* with the right knowledge about DMD internals (and enough free time on their hands >:-)) to pull it off. The problem with the current AA implementation is that it's schizophrenically split across DMD, aaA.d, and object.di. Martin Nowak recently cleaned it up somewhat (removed the horrible code duplication between aaA.d and object.di that used to be there) but fundamental issues remain, a major cause of which is the fact that aaA.d operates on typeinfo's rather than the direct types (this isn't a problem in and of itself, but the problem is that *only* AA keys have the benefit of their typeinfo's being available to AA functions, which means AA *values* that require non-trivial postblits and other such things are fundamentally broken in horrible ways). Moreover, DMD still retains way too much knowledge about AA internals, so sometimes it gets mapped to struct AssociativeArray, sometimes directly mapped to aaA.d, and sometimes a buggy inconsistent mixture of both. And the code that emits these different schizophrenic parts are sprinkled all over different unrelated parts of DMD, making any cleanup attempt rather challenging, to say the least. And of course, any non-correspondence between any of these parts means yet another AA bug waiting to happen. Cleaning up this mess once and for all will unquestionably do a world of good to D. T -- You are only young once, but you can stay immature indefinitely. -- azephrahelD is not only about arrays.It's a big plus. ;)[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 16 2013
On 09/16/13 22:38, Namespace wrote:Too much (language) change for too little gain; there are many, many much more important things that need to be fixed. Being able to have several user-defined kinds of arrays is a nice-to-have feature, but not one that determines whether the language is usable or not. artur[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 16 2013
On 09/16/13 22:52, H. S. Teoh wrote:On Mon, Sep 16, 2013 at 10:38:58PM +0200, Namespace wrote:I thought (s)he was asking about *arrays*, not AAs. There's no disagreement about removing AA magic - that does not involve language changes. arturI disagree that it's too high. It just needs *somebody* with the right knowledge about DMD internals (and enough free time on their hands >:-)) to pull it off.D is not only about arrays.It's a big plus. ;)[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 16 2013
On Monday, 16 September 2013 at 21:11:00 UTC, Artur Skawina wrote:On 09/16/13 22:52, H. S. Teoh wrote:Yes, he was. ;) Thanks for explanation.On Mon, Sep 16, 2013 at 10:38:58PM +0200, Namespace wrote:I thought (s)he was asking about *arrays*, not AAs. There's no disagreement about removing AA magic - that does not involve language changes. arturI disagree that it's too high. It just needs *somebody* with the right knowledge about DMD internals (and enough free time on their hands >:-)) to pull it off.D is not only about arrays.It's a big plus. ;)[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 16 2013
On Mon, Sep 16, 2013 at 10:59:10PM +0200, Artur Skawina wrote:On 09/16/13 22:38, Namespace wrote:[...] Hmm. I find D arrays just fine the way they are, actually. (In fact, I rather *liked* the way D arrays worked as compared with, say, C/C++.) What's wrong with them? T -- Famous last words: I *think* this will work...Too much (language) change for too little gain; there are many, many much more important things that need to be fixed. Being able to have several user-defined kinds of arrays is a nice-to-have feature, but not one that determines whether the language is usable or not.[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 16 2013
On 2013-09-17 00:53, H. S. Teoh wrote:Hmm. I find D arrays just fine the way they are, actually. (In fact, I rather *liked* the way D arrays worked as compared with, say, C/C++.) What's wrong with them?I guess one can complain about some of the built-in properties/functions, like sort. -- /Jacob Carlborg
Sep 16 2013
On 09/17/13 00:53, H. S. Teoh wrote:On Mon, Sep 16, 2013 at 10:59:10PM +0200, Artur Skawina wrote:Not that much, at least not enough to worry about it right now, considering all the other language issues. (eg some conversions, like to-bool, static-array-to-slice; syntax ambiguity [1]; some properties) But removing magic from the compiler and making the language more expressive, so that the magic could be done by the user, would be an improvement. Not a regression, which the original question implied. For example: 1) // in semi-pseudocode alias utf8string = utf8octet[]; utf8string s = "abc"; foreach (c; s) // iterate by codepoints, not bytes Yep, this is like what can be done today with built-in strings -- except that it could be done by overloading array-ops in 'utf8octect'. No type-specific compiler magic, and then you can use it for many other kinds of variable-element-length array types. 2) SIMD optimizations; again, w/o explicit compiler support. It could just map array ops to an optional 'static inline T.opArrayOp(string op, size_t minAlignent, B)(T[] a, B b)' method, etc. In general, much of the built-in compiler 'magic' gets in the way of emitting optimal code, for example the hardwired (d)runtime calls prevent many optimizations. (eg removing (hacking around for just one built-in type is easy enough) the 'typeid()' calls from your stand-alone AAs makes a huge difference. Or at least it did ~ a year ago when i looked at how much inherent overhead the std AAs have). artur [1] ---------------------------------------------------------------------- auto f(T[2] a) { /* 'a' is what it looks like - a static array, right? Oops... */ } template Tuple(A...) { alias Tuple = A; } alias T = Tuple!(int, double, long); ----------------------------------------------------------------------On 09/16/13 22:38, Namespace wrote:[...] Hmm. I find D arrays just fine the way they are, actually. (In fact, I rather *liked* the way D arrays worked as compared with, say, C/C++.) What's wrong with them?Too much (language) change for too little gain; there are many, many much more important things that need to be fixed. Being able to have several user-defined kinds of arrays is a nice-to-have feature, but not one that determines whether the language is usable or not.[1] Obviously, not a practical short term option for the existing D2 language. That's probably clear from the context, and the question was meant to be rhetorical -- but it could actually be done and would make sense; it's just not a change that would make enough of a difference on its own; the cost would be to high.Why to high? Too much compiler magic or dmd internal dependences?
Sep 17 2013
On Monday, 16 September 2013 at 19:21:47 UTC, H. S. Teoh wrote:On Mon, Sep 16, 2013 at 08:56:17PM +0200, Namespace wrote: [...]This demonstrates an interesting issue. I think the primary reason why you are complaining about AAs is not because their implementation is flawed but because you can't fix it without dmd's internals knowledge :) I always consider ability to hack dmd as important skill (at least in better language understanding because it is not defined by standard but by reference implementation) in D and that's why I am skeptical about many ideas proposed in form of DIPs - (unless they are proposed by those folks whose names often appear in dmd git commit log) because such proposals are not implementable without dmd's knowledge. I remember one point made recently by one regular D forum participant that it is more important 'to know the language itself', 'to be abstract from one particular implementation' rather then knowing 'dirty implementation details' to propose DIPs and that those who know dmd will eventually implement DIPs - yet number of DIPs is close to 50 and judging by ratio implemented DIPs/total DIPs it obvious that such assumption doesn't hold. As a result community is stuck with many features of language are flawed but they can be hardly fixed - plenty discussions and DIPs are generated but problems are not moved by an inch. I think if a person who has druntime/phobos commits to fix some issue but no dmd's one should ask in a forum thread/directly address to Walter/Kenji for a help request (addressing Walter should happen without hesitation because he is the first to be blamed :) ).I hate this NotNull struct hack. It is the same crap as the current scope solution. BTW: I'm curious which built-in feature will be removed next, maybe AA?[...] That wouldn't be a bad idea, actually. The current AA implementation is so horribly broken, and so wrong in so many ways (there are at least 75 bugs related to AA's, some of the worst of which are 11037, 11025, 10916, 10525, 10381, 10380, 10046, just to name a few), that it would do a world of good to get rid of them altogether, and then reintroduce a properly-designed library solution for them. Of course, in the meantime everyone whose code breaks because of that will form a mob to lynch me, so I'll have to survive long enough to get the library solution working first. :-P T
Sep 16 2013
On 9/16/13 11:56 AM, Namespace wrote:I hate this NotNull struct hack. It is the same crap as the current scope solution.Scoped variables in the language were a lot worse.BTW: I'm curious which built-in feature will be removed next, maybe AA?If we're diligent and lucky, hopefully.An annotation like Foo! f would be much nicer than NotNull!Foo or NotNull Foo, but it would be an agreement.Is annotation the only or main problem?And I agree absolute, to disable default CTor's by struct's was a huge mistake. But D is full of those. ;)They are not disabled. It seems many people are having trouble with getting default constructors to evaluate code, so I assume you mean that. One possibility (or first step) would be to relax the language to allow CTFE-executable code in default constructors. Andrei
Sep 16 2013
On Mon, Sep 16, 2013 at 12:28:21PM -0700, Andrei Alexandrescu wrote:On 9/16/13 11:56 AM, Namespace wrote:One thing I'd *really* like to have is proper escape analysis and inlining of scope delegates. I've been waiting a long time for this, and there are no signs of implementation in sight. :-(I hate this NotNull struct hack. It is the same crap as the current scope solution.Scoped variables in the language were a lot worse.I don't see what luck has to do with it... Currently, I lack just time and adequate understanding of DMD internals; if I had both, I'd rip out the AA implementation from DMD right now, and replace it with something saner. [...]BTW: I'm curious which built-in feature will be removed next, maybe AA?If we're diligent and lucky, hopefully.[...] Huh, what? struct S { this() {} } DMD output: /tmp/test.d(2): Error: constructor test.S.this default constructor for structs only allowed with disable and no body T -- You are only young once, but you can stay immature indefinitely. -- azephrahelAnd I agree absolute, to disable default CTor's by struct's was a huge mistake. But D is full of those. ;)They are not disabled.
Sep 16 2013
On Monday, 16 September 2013 at 19:28:22 UTC, Andrei Alexandrescu wrote:On 9/16/13 11:56 AM, Namespace wrote:Yes, we REALLY need this. I know that we can init struct fields via user-defined value, but for many cases is not enough. And in that days I remembered C++. Buy the way, what does it mean "They are not disabled"? struct Foo { int i = 5; //works } struct Bar { int i; this() { i = 5; } } DMD: src/app.d(10): Error: constructor app.Bar.this default constructor for structs only allowed with disable and no bodyAnd I agree absolute, to disable default CTor's by struct's was a huge mistake. But D is full of those. ;)They are not disabled. It seems many people are having trouble with getting default constructors to evaluate code, so I assume you mean that. One possibility (or first step) would be to relax the language to allow CTFE-executable code in default constructors.
Sep 16 2013
Long time not heard from each other. ;) On Monday, 16 September 2013 at 19:28:22 UTC, Andrei Alexandrescu wrote:On 9/16/13 11:56 AM, Namespace wrote:Why? The escaping problem could be solved, not? Wouldn't it be better, if scope would stay and would be rewritten internal to the library solution? The compiler could then detect and solve many of the current problems.I hate this NotNull struct hack. It is the same crap as the current scope solution.Scoped variables in the language were a lot worse.That was a joke of me. So I hope that is also a joke. Otherwise it would be a huge step in the C++ direction. If it wasn't a joke: what are the rationale for that?BTW: I'm curious which built-in feature will be removed next, maybe AA?If we're diligent and lucky, hopefully.My problem are the nullable classes. But I would be happy with an annotation.An annotation like Foo! f would be much nicer than NotNull!Foo or NotNull Foo, but it would be an agreement.Is annotation the only or main problem?Example?And I agree absolute, to disable default CTor's by struct's was a huge mistake. But D is full of those. ;)They are not disabled. It seems many people are having trouble with getting default constructors to evaluate code, so I assume you mean that. One possibility (or first step) would be to relax the language to allow CTFE-executable code in default constructors. Andrei
Sep 16 2013
On Monday, 16 September 2013 at 10:29:12 UTC, matovitch wrote:All your examples are great, thank you ! Is there a way to omit validate such that the compiler would call it implicitly ? For example : class C { ... } void fun( nonNull C c) { ... }; C c; fun(c); //compilation error since C is nullAs others have noted, the compiler cannot know what any of your attributes mean. But you can do this: class C { invariant() { validate(this); } }
Sep 16 2013
On Monday, 16 September 2013 at 07:36:13 UTC, simendsjo wrote:I don't have a full example without adding a lot of code, but this partial example might give you the gist of it. // This is the type that validates struct matches(string mustMatch) { alias re = ctRegex!(mustMatch); static string[] validate(T)(const ref T t) { static if(!isSomeString!T) static assert(0, "matches only works on strings, not "~T.stringof); return match(t, re).empty ? ["no match"] : null; } } // and this is the code that runs all validators for a variable void validate(alias T)(ref Appender!(string[]) app) { static if(isTupleWrapper!T) { validate!(T.Head)(app); validate!(T.Tail)(app); } else { foreach(memberAttr; getValidaterAttrs!T) { foreach(attr; memberAttr.Tail) { foreach(msg; attr.validate(T)) if(msg.length) app.put(msg); } } } } // .. And here is some of the plumbing string[] validate(Vars...)() { auto app = appender!(string[])(); validate!Vars(app); return app.data(); } // The getMembersAndAttributesWhere are templates in my little library that isn't released. Uses quite some custom __traits stuff, but it's basically __traits(getAttributes template getValidaterAttrs(alias T) { alias getValidaterAttrs = TypeTuple!(getMembersAndAttributesWhere!(T, isValidationAttr).Elements, getMembersAndAttributesWhere!(TypeOf!T, isValidationAttr).Elements); } // Well.. Incomplete template isValidationAttr(alias T) { enum isValidationAttr = hasMember!(TypeOf!T, "validate"); }Can I explicitly specify when I can use attribute? Something like this: attribute("field") struct matches(string mustMatch) { } string wrongAttribute { } class Foo { matches("[0-9]+") string someNumber; //OK, it's a field } matches("[0-9]+") //Error, it's a class, not a field class Bar { } wrongAttribute //Error, this attribute doesn't exist class C { }
Sep 19 2013
On 2013-09-20 08:59, ilya-stromberg wrote:Can I explicitly specify when I can use attribute? Something like this: attribute("field") struct matches(string mustMatch) { } string wrongAttribute { } class Foo { matches("[0-9]+") string someNumber; //OK, it's a field } matches("[0-9]+") //Error, it's a class, not a field class Bar { } wrongAttribute //Error, this attribute doesn't exist class C { }Unfortunately you can't. I tag all my structs which are supposed to be used as UDA's with a attribute UDA. struct attribute {} attribute struct matches(string mustMatch) {} Then I have some wrappers around __traits(getAttributes) that will, by default, only return UDA's that them self have the attribute UDA attached to them. https://github.com/jacob-carlborg/orange/blob/master/orange/core/Attribute.d -- /Jacob Carlborg
Sep 20 2013
On Friday, 20 September 2013 at 07:57:43 UTC, Jacob Carlborg wrote:On 2013-09-20 08:59, ilya-stromberg wrote:You could of course fix this in a library too. enum AttributeUsage { struct_ = 1 << 0, class_ = 1 << 1, //etc } struct attribute { AttributeUsage usage; } Then the library could give a compile-time error if you tries to use it where it's not meant to be.Can I explicitly specify when I can use attribute? Something like this: attribute("field") struct matches(string mustMatch) { } string wrongAttribute { } class Foo { matches("[0-9]+") string someNumber; //OK, it's a field } matches("[0-9]+") //Error, it's a class, not a field class Bar { } wrongAttribute //Error, this attribute doesn't exist class C { }Unfortunately you can't. I tag all my structs which are supposed to be used as UDA's with a attribute UDA. struct attribute {} attribute struct matches(string mustMatch) {} Then I have some wrappers around __traits(getAttributes) that will, by default, only return UDA's that them self have the attribute UDA attached to them. https://github.com/jacob-carlborg/orange/blob/master/orange/core/Attribute.d
Sep 20 2013
On 2013-09-20 16:12, simendsjo wrote:You could of course fix this in a library too. enum AttributeUsage { struct_ = 1 << 0, class_ = 1 << 1, //etc } struct attribute { AttributeUsage usage; } Then the library could give a compile-time error if you tries to use it where it's not meant to be.I'm not sure how I could do that. -- /Jacob Carlborg
Sep 23 2013
On Monday, 23 September 2013 at 07:47:32 UTC, Jacob Carlborg wrote:On 2013-09-20 16:12, simendsjo wrote:You can recurse into UDAs for attributes and pass along the type that had the uda. A static assert could verify that it's used on the correct type. (For my library, that would mean editing my getMembersAndAttributes template.)You could of course fix this in a library too. enum AttributeUsage { struct_ = 1 << 0, class_ = 1 << 1, //etc } struct attribute { AttributeUsage usage; } Then the library could give a compile-time error if you tries to use it where it's not meant to be.I'm not sure how I could do that.
Sep 23 2013