digitalmars.D - Modifying user-defined attributes. UDA templates.
- Yuriy (33/33) Mar 17 2014 Hello, I'm new to D, so please excuse me if i'm wrong anywhere.
- Jacob Carlborg (5/39) Mar 17 2014 Seems you want something similar to AST macros [1].
- Yuriy (3/7) Mar 17 2014 That really seems to do the job! However it seems like current
- Jacob Carlborg (4/6) Mar 17 2014 Yes, unfortunately will most likely never see AST macros in D.
- Dicebot (38/38) Mar 17 2014 Hello Yuriv,
Hello, I'm new to D, so please excuse me if i'm wrong anywhere. Ever since i've learned C++ and started practicing templates metaprogramming (after reading Andrei's book) i wished there was a language to be low-level as C++, productive as if interpreted (e.g. Python), and expressive as... well... here comes D! It's features are great, and specifically now i want to talk about UDA. This feature is what i lacked in C++, but as you know, appetite comes with eating, so i think there's still room for improvement in UDAs. The problem is current UDAs can't modify definition they're attached to. The solution is somewhere near Python's decorators, but of course, using compile-time templates or mixins. Here's an example: template MyAttr(string name, T) { } MyAttr class MyClass { ... class body } Which should evaluate to something like: class __MyClassTmpThatWillBeRemovedInCompileTime { ... class body } mixin(MyAttr!("MyClass", __MyClassTmpThatWillBeRemovedInCompileTime)); Next, MyAttr can modify the class, rename it, ignore it (in this case MyClass will not be available further), define something else instead of it. I could try and modify dmd to support it at least as a prototype, but before, i'd like to know whether such feature was already considered and rejected. Thanx.
Mar 17 2014
On Monday, 17 March 2014 at 09:17:33 UTC, Yuriy wrote:Hello, I'm new to D, so please excuse me if i'm wrong anywhere. Ever since i've learned C++ and started practicing templates metaprogramming (after reading Andrei's book) i wished there was a language to be low-level as C++, productive as if interpreted (e.g. Python), and expressive as... well... here comes D! It's features are great, and specifically now i want to talk about UDA. This feature is what i lacked in C++, but as you know, appetite comes with eating, so i think there's still room for improvement in UDAs. The problem is current UDAs can't modify definition they're attached to. The solution is somewhere near Python's decorators, but of course, using compile-time templates or mixins. Here's an example: template MyAttr(string name, T) { } MyAttr class MyClass { ... class body } Which should evaluate to something like: class __MyClassTmpThatWillBeRemovedInCompileTime { ... class body } mixin(MyAttr!("MyClass", __MyClassTmpThatWillBeRemovedInCompileTime)); Next, MyAttr can modify the class, rename it, ignore it (in this case MyClass will not be available further), define something else instead of it. I could try and modify dmd to support it at least as a prototype, but before, i'd like to know whether such feature was already considered and rejected. Thanx.Seems you want something similar to AST macros [1]. [1] http://wiki.dlang.org/DIP50 -- /Jacob Carlborg
Mar 17 2014
That really seems to do the job! However it seems like current mixins are going to be somewhat redundant with AST macros? On Monday, 17 March 2014 at 13:23:55 UTC, Jacob Carlborg wrote:Seems you want something similar to AST macros [1]. [1] http://wiki.dlang.org/DIP50 -- /Jacob Carlborg
Mar 17 2014
On 2014-03-17 15:35, Yuriy wrote:That really seems to do the job! However it seems like current mixins are going to be somewhat redundant with AST macros?Yes, unfortunately will most likely never see AST macros in D. -- /Jacob Carlborg
Mar 17 2014
Hello Yuriv, Currently declarative meta-programming is somewhat special in D compared to dynamic languages like python in a sense that all language entities are actually immutable. You can use those as a base for code generation but can't re-write existing symbols - this is a very basic property of the language and I highly doubt this will be ever changed (I would have been among first protesters, actually). That means that you need to organize your code differently to achieve similar usability in D. Two main patterns I am aware of: 1) Apply UDA's in context of some compile-time framework and put any modifications to be done on calling side while preserving actual function / class signatures as-is. For example, when vibe.d REST interface is annotated with rootPathFromName, it does not actually change anything in interface but indicates to route generation comile-time algorithm that it should be processed differently. In all other contexts interface still can be used as it has no UDA attached. 2) Use a private symbol as an input to generate actual public one. Something like this: SomeUDA private class MyClassImpl { // ... } // `generate` being some templated CTFE function that used reflection to // build code of new public class to mixin (with a name "MyClass") mixin(generate!(MyClassImpl, "MyClass")); There are several common utilities missing in Phobos to make such coding style much easier but will definitely improve in that regard ;) One example of function attribute implementation somewhat similar in spirit to Python decorators I have written for vibe.d : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/internal/meta/funcattr.d I will also be speaking on this topic on upcoming DConf.
Mar 17 2014
Hello Dicebot, I get your point. AST macros as they are explained in DIP50 are probably too powerful for a safe-by-default language. Also they could seduce users to implement custom syntax for cases, where D syntax could suffice. However, it's clearly seen from your example in vibe.d that using "decorators" expects users to know how to explicitly "evaluate" them. Otherwise, your "decorated" code could be misused if used "intuitively". Such approach effectively leads to at least two places in code, where you need to know about the logic of an attribute. I totally agree that modifying decorators could add another way of shooting your foot, but it seems to me that it's benefits are worth it. Besides, decorating a definition with an uninstantiated template would not break current syntax and current UDA logic. Also it could be potentially implemented by lowering, as described in my first message. Also, don't we love C++ for it's infinite number of ways to shoot your foot? =)
Mar 18 2014
On Tuesday, 18 March 2014 at 10:36:31 UTC, Yuriy wrote:However, it's clearly seen from your example in vibe.d that using "decorators" expects users to know how to explicitly "evaluate" them. Otherwise, your "decorated" code could be misused if used "intuitively". Such approach effectively leads to at least two places in code, where you need to know about the logic of an attribute.In vibe.d context it is intentionally designed that way. Same classes can be re-used as is for any other request handling - additional annotations make sense only within REST context. Splitting allows to achieve perfect decoupling here. In case you want to make persistent adjustment, approach (2) is recommended. It can effectively achieve the same result as true decoration with only difference that explicit mixin is required to hint both reader and compiler what is actually happening here. In real project it is up to your personal judgement which approach fits use case better.I totally agree that modifying decorators could add another way of shooting your foot, but it seems to me that it's benefits are worth it. Besides, decorating a definition with an uninstantiated template would not break current syntax and current UDA logic. Also it could be potentially implemented by lowering, as described in my first message.I think it is possible but gain does not seem to be worth complications. On a related notes, I'd also love to see "contained" AST macros, similar to how string mixins are always explicit.Also, don't we love C++ for it's infinite number of ways to shoot your foot? =)Well.. no. Not really :)
Mar 18 2014