Re: How to do reflection on alias symbols
On Friday, November 17, 2023 2:11:30 AM MST Arafel via Digitalmars-d-learn wrote: > I mean, in order to know if something is an `enum`, I need to do: > > ```d > enum isEnum(alias a) = is(typeof(a)) && !is(typeof()); > ``` > > which feels like the wrong approach, and too much error-prone. I also > fear I'm forgetting to consider some corner case. > > There is `is(E == enum)`, but it only works on types, and fails for > anonymous enums, because `typeof` returns the base type. Well, anonymous enums are what are called manifest constants, so they literally aren't enums as far as their type goes, and the type system does not consider them to be enums. They're just a way to declare constants (they're essentialy the D equivalent of using #define for constants in C/C++). Arguably, they should use a keyword other than enum (and that's been debated in the past), but it's unlikely to change at this point. So, if we were to add something to std.traits for them, it would probably be something more like isManifestConstant than isEnum. In spite of the keyword being used, they really aren't intended to be considered enums. - Jonathan M Davis
Re: How to do reflection on alias symbols
On 17/11/23 2:48, Jonathan M Davis wrote: On Thursday, November 16, 2023 6:04:43 PM MST Jonathan M Davis via Digitalmars-d-learn wrote: Actually, it looks like there's already an old bug report on the issue: https://issues.dlang.org/show_bug.cgi?id=12363 So, it has been reported, but it looks it's one of those that's gone under the radar. - Jonathan M Davis Thanks for finding it! I think that in general D could do with a more systematic approach to reflection. For me, it's one of its greatest features, and it's a bit of a pity that it needs to be done in such an ad-hoc manner with all kind of corner cases. I mean, in order to know if something is an `enum`, I need to do: ```d enum isEnum(alias a) = is(typeof(a)) && !is(typeof()); ``` which feels like the wrong approach, and too much error-prone. I also fear I'm forgetting to consider some corner case. There is `is(E == enum)`, but it only works on types, and fails for anonymous enums, because `typeof` returns the base type. I know that `std.traits` was precisely supposed to hide these dirty details, but as of now it also seems to be missing this kind of systematic approach: I'd like things like `isEnum!symbol`, and also `isAlias!symbol`, etc. But I think I digress a bit too much, this would be a topic rather for the general forum. Thanks again for your help!
Re: How to do reflection on alias symbols
On Thursday, November 16, 2023 6:04:43 PM MST Jonathan M Davis via Digitalmars-d-learn wrote: > I would suggest that you open up a bug report for it - > https://issues.dlang.org - and certainly, there's a good argument that what > you're seeing here is a bug. I fully expect that what you're trying do just > wasn't properly considered previously and thus was not dealt with properly > when the other bugs for visibility attributes on aliases were fixed however > many years ago that was now. I very much doubt that what you're seeing is > the intended behavior - or at least I fully expect that if Walter or one of > the other compiler devs sees the issue, they will agree that what you're > trying to do should work. Actually, it looks like there's already an old bug report on the issue: https://issues.dlang.org/show_bug.cgi?id=12363 So, it has been reported, but it looks it's one of those that's gone under the radar. - Jonathan M Davis
Re: How to do reflection on alias symbols
On Thursday, November 16, 2023 3:03:25 AM MST Arafel via Digitalmars-d-learn wrote: > Hi all, > > Please consider the following currently non-working code: > > ```d > struct bar { > public alias pubInt = int; > private alias privInt = int; > } > > static foreach(member ; __traits(allMembers, bar)) { > // Error: argument `int` has no visibility > pragma(msg, __traits(getVisibility, __traits(getMember, bar, member))); > } > ``` > > Is there any way to get the visibility, or more generically to reflect > on an alias member as itself and not as the symbol pointed to without > resorting to nasty __trait(compiles,...) tricks that fail more often > than not? Someone may be able to give you some advice on how to better deal with this problem, but in general, aliases don't really exist as far as the compiler is concerned. They get translated to the original type and handled that way rather than treated as a separate type that translates to another type. They exist enough that you can do stuff like give them different visibility attributes for the original symbol, but that pretty much just affects whether you can use the alias, and then it gets replaced with the real thing immediately. As it is, IIRC, it was previously the case that there were bugs where visibility attributes did not affect aliases properly, so it's not at all surprising if there isn't a good way to access the visibility attribute of the alias itself. I would suggest that you open up a bug report for it - https://issues.dlang.org - and certainly, there's a good argument that what you're seeing here is a bug. I fully expect that what you're trying do just wasn't properly considered previously and thus was not dealt with properly when the other bugs for visibility attributes on aliases were fixed however many years ago that was now. I very much doubt that what you're seeing is the intended behavior - or at least I fully expect that if Walter or one of the other compiler devs sees the issue, they will agree that what you're trying to do should work. - Jonathan M Davis
How to do reflection on alias symbols
Hi all, Please consider the following currently non-working code: ```d struct bar { public alias pubInt = int; private alias privInt = int; } static foreach(member ; __traits(allMembers, bar)) { // Error: argument `int` has no visibility pragma(msg, __traits(getVisibility, __traits(getMember, bar, member))); } ``` Is there any way to get the visibility, or more generically to reflect on an alias member as itself and not as the symbol pointed to without resorting to nasty __trait(compiles,...) tricks that fail more often than not?
Re: Reflection on the book D web development.
& Golang has Martini which is quite easy to use, https://www.youtube.com/watch?v=tUFzdUIjVRg
Re: Reflection on the book D web development.
On Wednesday, 25 November 2020 at 17:26:44 UTC, Alaindevos wrote: hunt-http has no documentation and does not looks usable to me. What looks usable is kemal & the crystal language, https://kemalcr.com/guide/ Looks like Sinatra. That makes sense given the relationship of Crystal to Ruby. Many languages have a Sinatra-inspired framework, but to my knowledge not D. I think Adam Ruppe's libraries are closer to that approach.
Re: Reflection on the book D web development.
hunt-http has no documentation and does not looks usable to me. What looks usable is kemal & the crystal language, https://kemalcr.com/guide/
Re: Reflection on the book D web development.
On Saturday, 21 November 2020 at 16:18:39 UTC, Alaindevos wrote: It's not my related to a lack of knowledge of the d-language but the complexity of the vibe.d framework itself. What I understand are : 1: jade/diet .dt templates, inheritance,includes,markdown. 2: A simple form with POST method. Then it stops. What I find too complex: - Sessions, session data , session variables - Handler functions and delegates, compile-time reflection, prefixes, annotation. - Authentication - Validating user input This can be improved by improving documentation in very small steps. As comparison here a tutorial of ruby-flask which uses only small steps so everything can easily and completely be understood. Something like that for vibe.d would be very interesting. https://www.youtube.com/watch?v=3mwFC4SHY-Y May or may not be related, but I eventually gave up on that book myself. It felt as if it were written for experienced web developers wanting to use D for things they were doing in other languages. It's been a long time now, though, so I don't recall anything specific.
Re: Reflection on the book D web development.
It's not my related to a lack of knowledge of the d-language but the complexity of the vibe.d framework itself. What I understand are : 1: jade/diet .dt templates, inheritance,includes,markdown. 2: A simple form with POST method. Then it stops. What I find too complex: - Sessions, session data , session variables - Handler functions and delegates, compile-time reflection, prefixes, annotation. - Authentication - Validating user input This can be improved by improving documentation in very small steps. As comparison here a tutorial of ruby-flask which uses only small steps so everything can easily and completely be understood. Something like that for vibe.d would be very interesting. https://www.youtube.com/watch?v=3mwFC4SHY-Y
Re: Reflection on the book D web development.
On Friday, 20 November 2020 at 19:12:38 UTC, Alaindevos wrote: I bought the book "D Web Development". I understand only 20% of the book,the other 80% is way above my head. Compare, I own a book on flask development, and I understand 100% of it. Which means I can use dlang for anything except QT and serious web development ... How would you like this to be improved? I'm personally interested in making vibe.d more accessible.
Re: Reflection on the book D web development.
On Friday, 20 November 2020 at 19:12:38 UTC, Alaindevos wrote: I bought the book "D Web Development". I understand only 20% of the book,the other 80% is way above my head. Compare, I own a book on flask development, and I understand 100% of it. Which means I can use dlang for anything except QT and serious web development ... Could you explain some of the things that you found particularly challenging about the book? What level of D proficiency did you have before you started with the book?
Reflection on the book D web development.
I bought the book "D Web Development". I understand only 20% of the book,the other 80% is way above my head. Compare, I own a book on flask development, and I understand 100% of it. Which means I can use dlang for anything except QT and serious web development ...
Re: Run-time reflection for class inheritance
On Sunday, 1 December 2019 at 14:42:46 UTC, Adam D. Ruppe wrote: You can get the type at runtime by simply casting it... if(auto c = cast(EventSocket) event) { // is an event socket } Thanks. I guess you need to be careful about which order you do those tests so as not to cast to more general types before testing for specific ones. I also came up with ``` if (typeid(event) == typeid(EventTimer)) { // do something } ``` The reason I was leaning toward the first one is that it could be put in a switch as it's just string compares. I guess having it cast as part of the check is useful.
Re: Run-time reflection for class inheritance
On Sunday, 1 December 2019 at 12:26:03 UTC, Michael Green wrote: I don't know if this would be a sensible approach to try and get at the actual class types for objects stored in some container at runtime? You can get the type at runtime by simply casting it... if(auto c = cast(EventSocket) event) { // is an event socket } and then you can actually use the c object too. Or if you put the necessary functionality in the interface then you simply call the method - this is better object-oriented design as it reduces the necessary knowledge for the function to use the object.
Re: Run-time reflection for class inheritance
On Sunday, 1 December 2019 at 12:26:03 UTC, Michael Green wrote: interface Event { [note to self - shouldn't make last minute checks and reverse them by hand before posting] That should of course read: class Event {
Run-time reflection for class inheritance
I don't know if this would be a sensible approach to try and get at the actual class types for objects stored in some container at runtime? I have noticed that this approach doesn't work if Event is an interface rather than a ancestor class. ``` import std.stdio; import std.string; import std.traits; import std.conv; interface Event { void report() { writeln("an event"); } } class EventTimer : Event { override void report() { writeln("timer event"); } } class EventSocket: Event { override void report() { writeln("socket event"); } } void main(string[] args) { Event[] events; foreach (arg; args[1..$]) { // just something to pick actual type at runtime if (to!int(arg) > 5) { events ~= new EventTimer(); } else { events ~= new EventSocket(); } } foreach (event; events) { switch (event.classinfo.name) { case fullyQualifiedName!EventTimer: writeln("found timer event"); break; case fullyQualifiedName!EventSocket: writeln("found socket event"); break; default: throw new Exception("unknown event type"); break; } event.report(); } } ```
Re: Blog Post #0039 - File Dialog V - Adding SaveAs and Titlebar Filename Reflection
Hi WebFreak. I'm glad you're getting something out of it. I started this because it's the kind of thing I wished was out there. It's good to know I'm not the only one. On Tuesday, 28 May 2019 at 12:58:12 UTC, WebFreak001 wrote: Could you maybe add screenshots to each blog post? I've had a ton (Well, four... Five? Six?) requests to do them and I have started down that road, but it's going to take a bit of time what with everything else I've got going on ATM. They could be shown for example right at the top of each post and maybe a thumbnail in the post list and that way greatly simplify searching a tutorial of interest and also massively help with sharing links to your posts online where OpenGraph or Twitter images are embedded. (see https://gethead.info/ for good examples how to add these meta tags) I'll see if I can sort this out. Is the source code of your site available somewhere? I'm not sure what you mean by this... the HTML? the Jekyll code? Or are you asking about the example files? Because the examples are all there with links in the blog posts, if that's what you're asking about. But if you're asking about the HTML/Jekyll/whatever, I have to ask: why do you want access? Also it would be nice if it supported HTTPS. (LetsEncrypt certificates are free and easy to setup for this) Why would I need secure pages?
Re: Blog Post #0039 - File Dialog V - Adding SaveAs and Titlebar Filename Reflection
On Tuesday, 28 May 2019 at 09:47:23 UTC, Ron Tarrant wrote: Good day to you all. 'Tis another Tuesday and time for a new blog post. This is a continuation of the series on Dialogs and further, a continuation of the mini-series-within-a-series on file Dialogs. The subject is in the title as is fitting for a blog post about putting things in the titlebar. You can find it here: http://gtkdcoding.com/2019/05/28/0039-file-save-as-dialog.html nice work! Such regular tutorials are always great for the community and just recently recommended it to someone asking for one. Could you maybe add screenshots to each blog post? They could be shown for example right at the top of each post and maybe a thumbnail in the post list and that way greatly simplify searching a tutorial of interest and also massively help with sharing links to your posts online where OpenGraph or Twitter images are embedded. (see https://gethead.info/ for good examples how to add these meta tags) Is the source code of your site available somewhere? Also it would be nice if it supported HTTPS. (LetsEncrypt certificates are free and easy to setup for this)
Blog Post #0039 - File Dialog V - Adding SaveAs and Titlebar Filename Reflection
Good day to you all. 'Tis another Tuesday and time for a new blog post. This is a continuation of the series on Dialogs and further, a continuation of the mini-series-within-a-series on file Dialogs. The subject is in the title as is fitting for a blog post about putting things in the titlebar. You can find it here: http://gtkdcoding.com/2019/05/28/0039-file-save-as-dialog.html
Re: Derived classes? Reflection
On Saturday, 13 April 2013 at 17:50:00 UTC, Tofu Ninja wrote: On Saturday, 13 April 2013 at 17:45:12 UTC, Tofu Ninja wrote: Maybe this is helpfully: http://forum.dlang.org/thread/scgjnudclnwlbdqqd...@forum.dlang.org Oddly enough, I found that at about the same time you posted it. Sadly this does not provide a compile time solution, only runtime. I wonder if one could use this to first spawn a process at compile type and then spit out the information and then process that info at compile time(say from a text file).
Re: Converting member variables to strings with using reflection from base class
On Friday, 22 December 2017 at 22:09:05 UTC, H. S. Teoh wrote: On Fri, Dec 22, 2017 at 09:13:31PM +, kerdemdemir via Digitalmars-d-learn wrote: I want to make a logging function for member variables by using reflection. [...] class B { void Log() { auto a = [__traits(derivedMembers, D)]; foreach(memberName; a) { // Somehow write only member variables with their names // Result should be : a = 4.0, b = 3.0 Try this: import std.traits : FieldNameTuple; foreach (memberName; FieldNameTuple!B) { writefln("%s = %s", memberName, mixin("this." ~ memberName)); } T and then turn it into a LoggerMixin with a mixin template and re-use it any time you want. import std.stdio : writeln, writefln; import std.traits : FieldNameTuple; mixin template LoggerMixin() { void Log() { foreach (memberName; FieldNameTuple!(typeof(this))) { writefln("%s = %s", memberName, mixin("this." ~ memberName)); } } } struct S { int x; bool y; double z; mixin LoggerMixin; } void main() { S s1 = S(int.min, true, ); S s2 = S(int.max, false, ); s1.Log(); s2.Log(); }
Re: Converting member variables to strings with using reflection from base class
On Fri, Dec 22, 2017 at 09:13:31PM +, kerdemdemir via Digitalmars-d-learn wrote: > I want to make a logging function for member variables by using reflection. [...] > class B > { > void Log() > { > auto a = [__traits(derivedMembers, D)]; > foreach(memberName; a) { > // Somehow write only member variables with their names > // Result should be : a = 4.0, b = 3.0 Try this: import std.traits : FieldNameTuple; foreach (memberName; FieldNameTuple!B) { writefln("%s = %s", memberName, mixin("this." ~ memberName)); } T -- People walk. Computers run.
Converting member variables to strings with using reflection from base class
I want to make a logging function for member variables by using reflection. import std.stdio; class D : B { override void foo() { a = 4.0; b = 3.0; } double a; double b; } class B { void Log() { auto a = [__traits(derivedMembers, D)]; foreach(memberName; a) { // Somehow write only member variables with their names // Result should be : a = 4.0, b = 3.0 } } void foo() { } } void main() { auto b = new D; b.Log(); } As I wrote in the comments I want to see member variable's name and its value. What is the best way to achieve that? Erdem
Re: learning reflection in D
05.10.2017 18:04, Adam D. Ruppe пишет: On Thursday, 5 October 2017 at 14:59:10 UTC, drug wrote: 1) why .stringof and typeid() is equal logically and different in fact? What is difference between them? Is it that stringof compile time and typeid runtime things? Anyway wouldn't it be better they will equal both logically and literally? stringof is a static debugging aid, just a string that kinda represents it in code. It isn't guaranteed to match anything, but should be enough that when you eyeball it it points you in the right direction... you shouldn't rely on it to be anything specific. typeid, on the other hand, is a published, documented object with methods and defined comparisons. So that's one difference. The other one is indeed compile time vs runtime: stringof is purely compile time, whereas typeid() returns a runtime object on a runtime object. To see the difference, try: Object o = new MyClass(); typeid(o); You'll see it is MyClass, but the static versions (stringof, typeof, etC) will all think of it as Object. 2) Where do these attributes come from? I mean `pure nothrow @nogc @safe` except `@property` that I set explicitly? You didn't specify a return value for those functions, which meant the compiler inferred a bunch about it. It inferred the return value and those other attributes to fill in the gap. If you gave an explicit return value `@property int` or `@property void`, then it wouldn't automatically fill stuff in anymore. Thank you, Adam!
Re: learning reflection in D
On Thursday, 5 October 2017 at 14:59:10 UTC, drug wrote: 1) why .stringof and typeid() is equal logically and different in fact? What is difference between them? Is it that stringof compile time and typeid runtime things? Anyway wouldn't it be better they will equal both logically and literally? stringof is a static debugging aid, just a string that kinda represents it in code. It isn't guaranteed to match anything, but should be enough that when you eyeball it it points you in the right direction... you shouldn't rely on it to be anything specific. typeid, on the other hand, is a published, documented object with methods and defined comparisons. So that's one difference. The other one is indeed compile time vs runtime: stringof is purely compile time, whereas typeid() returns a runtime object on a runtime object. To see the difference, try: Object o = new MyClass(); typeid(o); You'll see it is MyClass, but the static versions (stringof, typeof, etC) will all think of it as Object. 2) Where do these attributes come from? I mean `pure nothrow @nogc @safe` except `@property` that I set explicitly? You didn't specify a return value for those functions, which meant the compiler inferred a bunch about it. It inferred the return value and those other attributes to fill in the gap. If you gave an explicit return value `@property int` or `@property void`, then it wouldn't automatically fill stuff in anymore.
learning reflection in D
https://run.dlang.io/is/8LbmzG 1) why .stringof and typeid() is equal logically and different in fact? What is difference between them? Is it that stringof compile time and typeid runtime things? Anyway wouldn't it be better they will equal both logically and literally? 2) Where do these attributes come from? I mean `pure nothrow @nogc @safe` except `@property` that I set explicitly?
Re: Deduplicating template reflection code
On Friday, 14 April 2017 at 17:57:49 UTC, Johannes Pfau wrote: Am Fri, 14 Apr 2017 13:41:45 + schrieb Moritz Maxeiner: [...] Great, thanks that's exactly the solution I wanted. Figuring this out by myself is a bit above my template skill level ;-) -- Johannes No problem, I often enough encounter instances of THE DAMNED COMPILER JUST NOT DOING WHAT I WANT being frustrated with templates myself. Usually looking at phobos code helps, though.
Re: Deduplicating template reflection code
Am Fri, 14 Apr 2017 13:41:45 + schrieb Moritz Maxeiner: > On Friday, 14 April 2017 at 11:29:03 UTC, Johannes Pfau wrote: > > > > Is there some way to wrap the 'type selection'? In pseudo-code > > something like this: > > > > enum FilteredOverloads(API) = ... > > > > foreach(Overload, FilteredOverloads!API) > > { > > > > } > > Sure, but that's a bit more complex: > > --- > [...] // IgnoreUDA declaration > [...] // isSpecialFunction declaration > > /// > template FilteredOverloads(API) > { > import std.traits : hasUDA, isSomeFunction, > MemberFunctionsTuple; > import std.meta : staticMap; > import std.typetuple : TypeTuple; > > enum derivedMembers = __traits(derivedMembers, API); > > template MemberOverloads(string member) > { > static if (__traits(compiles, __traits(getMember, API, > member))) > { > static if (isSomeFunction!(__traits(getMember, API, > member)) > && !hasUDA!(__traits(getMember, API, > member), IgnoreUDA) > && !isSpecialFunction!member) { > alias MemberOverloads = > MemberFunctionsTuple!(API, member); > } else { > alias MemberOverloads = TypeTuple!(); > } > } else { > alias MemberOverloads = TypeTuple!(); > } > } > > alias FilteredOverloads = staticMap!(MemberOverloads, > derivedMembers); > } > > //pragma(msg, FilteredOverloads!API); > foreach(Overload; FilteredOverloads!API) { > // function dependent code here > } > --- > > Nested templates and std.meta are your best friends if this is > the solution you prefer :) Great, thanks that's exactly the solution I wanted. Figuring this out by myself is a bit above my template skill level ;-) -- Johannes
Re: Deduplicating template reflection code
On Friday, 14 April 2017 at 11:29:03 UTC, Johannes Pfau wrote: Is there some way to wrap the 'type selection'? In pseudo-code something like this: enum FilteredOverloads(API) = ... foreach(Overload, FilteredOverloads!API) { } Sure, but that's a bit more complex: --- [...] // IgnoreUDA declaration [...] // isSpecialFunction declaration /// template FilteredOverloads(API) { import std.traits : hasUDA, isSomeFunction, MemberFunctionsTuple; import std.meta : staticMap; import std.typetuple : TypeTuple; enum derivedMembers = __traits(derivedMembers, API); template MemberOverloads(string member) { static if (__traits(compiles, __traits(getMember, API, member))) { static if (isSomeFunction!(__traits(getMember, API, member)) && !hasUDA!(__traits(getMember, API, member), IgnoreUDA) && !isSpecialFunction!member) { alias MemberOverloads = MemberFunctionsTuple!(API, member); } else { alias MemberOverloads = TypeTuple!(); } } else { alias MemberOverloads = TypeTuple!(); } } alias FilteredOverloads = staticMap!(MemberOverloads, derivedMembers); } //pragma(msg, FilteredOverloads!API); foreach(Overload; FilteredOverloads!API) { // function dependent code here } --- Nested templates and std.meta are your best friends if this is the solution you prefer :)
Re: Deduplicating template reflection code
Am Fri, 14 Apr 2017 08:55:48 + schrieb Moritz Maxeiner: > > mixin Foo!(API, (MethodType) { > // function dependent code here > }); > foo(); > --- > > Option 2: Code generation using CTFE > > --- > string genFoo(alias API, string justDoIt) > { > import std.array : appender; > auto code = appender!string; > code.put(`[...]1`); > code.put(`foreach (MethodType; overloads) {`); > code.put(justDoIt); > code put(`}`); > code.put(`[...]2`); > } > > mixin(genFoo!(API, q{ > // function dependent code here > })()); > --- > > Personally, I'd consider the second approach to be idiomatic, but > YMMW. I'd prefer the first approach, simply to avoid string mixins. I think these can often get ugly ;-) Is there some way to wrap the 'type selection'? In pseudo-code something like this: enum FilteredOverloads(API) = ... foreach(Overload, FilteredOverloads!API) { } -- Johannes
Re: Deduplicating template reflection code
On Friday, 14 April 2017 at 08:24:00 UTC, Johannes Pfau wrote: I've got this code duplicated in quite some functions: - [...]1 foreach (MethodType; overloads) { // function dependent code here } [...]2 What's the idiomatic way to refactor / reuse this code fragment? -- Johannes Your options are at least the following two (both untested, but should work): Option 1: Template Mixins --- mixin template Foo(alias API, Dg) { void foo() { [...]1 foreach (MethodType; overloads) { Dg(MethodType); } [...]2 } } mixin Foo!(API, (MethodType) { // function dependent code here }); foo(); --- Option 2: Code generation using CTFE --- string genFoo(alias API, string justDoIt) { import std.array : appender; auto code = appender!string; code.put(`[...]1`); code.put(`foreach (MethodType; overloads) {`); code.put(justDoIt); code put(`}`); code.put(`[...]2`); } mixin(genFoo!(API, q{ // function dependent code here })()); --- Personally, I'd consider the second approach to be idiomatic, but YMMW.
Re: Deduplicating template reflection code
On Friday, 14 April 2017 at 08:24:00 UTC, Johannes Pfau wrote: I've got this code duplicated in quite some functions: - foreach (member; __traits(derivedMembers, API)) { // Guards against private members static if (__traits(compiles, __traits(getMember, API, member))) { static if (isSomeFunction!(__traits(getMember, API, member)) && !hasUDA!(__traits(getMember, API, member), IgnoreUDA) && !isSpecialFunction!member) { alias overloads = MemberFunctionsTuple!(API, member); foreach (MethodType; overloads) { // function dependent code here } } } } What's the idiomatic way to refactor / reuse this code fragment? -- Johannes The Idiomatic way would be to wrap it inside another template. In a year or so you won't need to worry about template overhead anymore, (if I succeed that is :) )
Deduplicating template reflection code
I've got this code duplicated in quite some functions: - foreach (member; __traits(derivedMembers, API)) { // Guards against private members static if (__traits(compiles, __traits(getMember, API, member))) { static if (isSomeFunction!(__traits(getMember, API, member)) && !hasUDA!(__traits(getMember, API, member), IgnoreUDA) && !isSpecialFunction!member) { alias overloads = MemberFunctionsTuple!(API, member); foreach (MethodType; overloads) { // function dependent code here } } } } What's the idiomatic way to refactor / reuse this code fragment? -- Johannes
Re: Reflection in D
thank you, the second method works perfectly. I have one last problem, I start thread and in thread Protocol.GetInstance(id) return null while in main thread it works. My class : class ProtocolMessageManager { private static TypeInfo_Class[uint] m_types; shared static this() { foreach(mod; ModuleInfo) { foreach(TypeInfo_Class lc; mod.localClasses) { if(lc.base is typeid(NetworkMessage)) { NetworkMessage c = cast(NetworkMessage)lc.create(); ProtocolMessageManager.m_types[c.MessageId] = lc; } } } } public static NetworkMessage GetInstance(uint id) { auto v = (id in ProtocolMessageManager.m_types); if (v !is null) return cast(NetworkMessage)ProtocolMessageManager.m_types[id].create(); else return null; } }
Re: Reflection in D
On Saturday, 28 January 2017 at 07:10:27 UTC, medhi558 wrote: I have a last question, currently i use : if(lc.name.indexOf("protocol.messages") != -1) If they're all in the same module, you can also use the compile time reflection to scan the module for classes. That's foreach(memberName; __traits(allMembers, mixin(__MODULE__))) static if(is(__traits(getMember, mixin(__MODULE__), memberName) : NetworkMessage) { if(memberName == runtime_string_of_class_name) { auto msg = new __traits(getMember, mixin(__MODULE__), memberName); // populate msg } } Or something like that. The compile time stuff works well when everything is in a shared module. If not, the runtime stuff has methods `base` and `interfaces` you can scan for your class. So like foreach(c; mod.localClasses if(c.base is typeid(NetworkMessage) { // work with it } Notice it is typeid for runtime, typeof at compile time, and this only gets direct children of NetworkMessage (though you could walk up the parent list to check more).
Re: Reflection in D
On Saturday, 28 January 2017 at 09:05:13 UTC, rumbu wrote: As long as your class has a default constructor, you can use directly Object.factory(id): public static NetworkMessage GetInstance(string id) { return cast(NetworkMessage)(Object.factory(id)); } It isn't possible. My function when I receive data : private void ReceivedData(char[] buffer) { BinaryReader reader = new BinaryReader(); uint id = reader.ReadUInt(); uint length = reader.ReadInt(); if(length > reader.Available.length) { //waiting for the rest return; } NetworkMessage message = ProtocolMessageManager.GetInstance(id); message.Deserialize(); //. }
Re: Reflection in D
abstract class NetworkMessage { uint MessageId; // } override class QueueStatusUpdateMessage : NetworkMessage { uint MessageId = 1; // } override class Message2 : NetworkMessage { uint MessageId = 2; // } override class Message3 : NetworkMessage { uint MessageId = 3; // } And I would like to retrieve all the classes that are based on NetworkMessage. class ProtocolMessageManager { private static TypeInfo_Class[uint] m_types; public static void Init() { foreach(mod; ModuleInfo) { foreach(TypeInfo_Class lc; mod.localClasses) { if() //lc is NetworkMessage so { NetworkMessage c = cast(NetworkMessage)lc.create(); ProtocolMessageManager.m_types[c.MessageId] = lc; } } } } public static NetworkMessage GetInstance(string id) { auto v = (id in ProtocolMessageManager.m_types); if (v !is null) return cast(NetworkMessage)ProtocolMessageManager.m_types[id].create(); else return null; } }
Re: Reflection in D
On Saturday, 28 January 2017 at 07:03:51 UTC, medhi558 wrote: public static NetworkMessage GetInstance(string id) { auto v = (id in ProtocolMessageManager.m_types); if (v !is null) return cast(NetworkMessage)ProtocolMessageManager.m_types[id].create(); else return null; } } As long as your class has a default constructor, you can use directly Object.factory(id): public static NetworkMessage GetInstance(string id) { return cast(NetworkMessage)(Object.factory(id)); }
Re: Reflection in D
On Saturday, 28 January 2017 at 08:18:15 UTC, medhi558 wrote: On Saturday, 28 January 2017 at 07:39:51 UTC, rumbu wrote: On Saturday, 28 January 2017 at 07:10:27 UTC, medhi558 wrote: I have a last question, currently i use : if(lc.name.indexOf("protocol.messages") != -1) To know if the class is a NetworkMessage, Would be possible to do this if(lc is NetworkMessage) Sorry for my English, i speak french. if (auto nm = cast(NetworkMessage)lc) { //do something with nm } It doesn't work because lc is TypeInfo_Class In this case: if (lc == typeid(NetworkMessage))
Re: Reflection in D
On Saturday, 28 January 2017 at 07:39:51 UTC, rumbu wrote: On Saturday, 28 January 2017 at 07:10:27 UTC, medhi558 wrote: I have a last question, currently i use : if(lc.name.indexOf("protocol.messages") != -1) To know if the class is a NetworkMessage, Would be possible to do this if(lc is NetworkMessage) Sorry for my English, i speak french. if (auto nm = cast(NetworkMessage)lc) { //do something with nm } It doesn't work because lc is TypeInfo_Class
Re: Reflection in D
On Saturday, 28 January 2017 at 07:10:27 UTC, medhi558 wrote: I have a last question, currently i use : if(lc.name.indexOf("protocol.messages") != -1) To know if the class is a NetworkMessage, Would be possible to do this if(lc is NetworkMessage) Sorry for my English, i speak french. if (auto nm = cast(NetworkMessage)lc) { //do something with nm }
Re: Reflection in D
I have a last question, currently i use : if(lc.name.indexOf("protocol.messages") != -1) To know if the class is a NetworkMessage, Would be possible to do this if(lc is NetworkMessage) Sorry for my English, i speak french.
Re: Reflection in D
I develop a game server. Currently I use a switch : import protocol.messages.connection.Message1; import protocol.messages.connection.Message2; import protocol.messages.queues.Message3; import .. import protocol.messages.NetworkMessage; class ProtocolMessageManager { public static NetworkMessage GetInstance(uint id) { switch(id) { case Message1.Id: return new Message1(); case Message2.Id: return new Message2(); . default: return null; } } } what I want to do : import protocol.messages.NetworkMessage; class ProtocolMessageManager { private static TypeInfo_Class[uint] m_types; public static void Init() { foreach(mod; ModuleInfo) { foreach(TypeInfo_Class lc; mod.localClasses) { if(lc.name.indexOf("protocol.messages") != -1) { NetworkMessage c = cast(NetworkMessage)lc.create(); ProtocolMessageManager.m_types[c.MessageId] = lc; } } } } public static NetworkMessage GetInstance(string id) { auto v = (id in ProtocolMessageManager.m_types); if (v !is null) return cast(NetworkMessage)ProtocolMessageManager.m_types[id].create(); else return null; } }
Re: Reflection in D
On Friday, 27 January 2017 at 21:02:13 UTC, medhi558 wrote: Hello, I would like to know if it is possible to recover all classes in the project in D. Yes, `foreach(mod; ModuleInfo) foreach(lc; mod.localClasses)`... but why do you want it? That facility is kinda limited in doing many things with.
Reflection in D
Hello, I would like to know if it is possible to recover all classes in the project in D. Example in c# : Assembly asm = Assembly.GetAssembly(typeof(MyClass)); foreach (Type type in asm.GetTypes()) { }
Re: Reflection: Order of fields guaranteed?
On Friday, 21 October 2016 at 01:51:44 UTC, Stefan Koch wrote: On Friday, 21 October 2016 at 01:34:44 UTC, Nick Sabalausky wrote: When using reflection to obtain the fields of a class/struct, is there any guarantee that the order is the same as the order the fields are defined? Yes they should always come in lexical order. For classes, the spec disagrees, even though it might be true using current compilers. https://dlang.org/spec/class.html#fields "The D compiler is free to rearrange the order of fields in a class to optimally pack them in an implementation-defined manner. ... Explicit control of field layout is provided by struct/union types, not classes."
Re: Reflection: Order of fields guaranteed?
On Friday, 21 October 2016 at 01:34:44 UTC, Nick Sabalausky wrote: When using reflection to obtain the fields of a class/struct, is there any guarantee that the order is the same as the order the fields are defined? Yes they should always come in lexical order.
Reflection: Order of fields guaranteed?
When using reflection to obtain the fields of a class/struct, is there any guarantee that the order is the same as the order the fields are defined?
Re: Probably a real simple compile-time reflection question?
On Saturday, 9 July 2016 at 21:12:24 UTC, WhatMeWorry wrote: foreach( i, str; myClassMembers) What are you doing to get myClassMembers? If it is __traits(allMembers), it just gives you the *names* of the members. To get the actual thing, you then do __traits(getMember, object, str) and can check the type of that. Also, is there a way to get __traits(allMembers to work recursively? Say, with struct containing structs. You can always just call it recursively once you get the member :)
Probably a real simple compile-time reflection question?
class C { this(){ _i = 0; _j = 0; } void setVar(int i) { _i = i; } int getVar() { return _i; } int _i; int _j; } writeln("C"); foreach( i, str; myClassMembers) { writeln("member ", i, " = ", str); TypeInfo ti = typeid(str); writeln("type id is ", ti); writeln("type is ", typeof(str).stringof); } C member 0 = __ctor type id is immutable(char)[] type is string member 1 = _i type id is immutable(char)[] type is string member 2 = setVar type id is immutable(char)[] type is string member 3 = getVar type id is immutable(char)[] type is string . . . the same all the way through the class I'm trying to get at least the type int for the _i member? Also, is there a way to get __traits(allMembers to work recursively? Say, with struct containing structs. Thanks, kyle
Request for feedback on reflection based module
Hi I'm trying out D and wanted to try some features cpp doesn't have yet. So I put together a small json parsing, generating looking based on reflection. Is there anything wrong with how I'm working with it in the module? https://github.com/rharriso/JSONInflater.d Thanks in advance
package reflection
In the video Case Studies In Simplifying Code With Compile-Time Reflection [was pointed out][0] that it is possible to reflect on imported packages. So, I tried: reflection.d: ``` import std.stdio; import test.module1; import test.module2; void main() { foreach (m; __traits(allMembers, mixin(__MODULE__))) { writeln(m); } writeln(--); foreach (m; __traits(allMembers, test)) { writeln(m); } } ``` test/module1.d: ``` module test.module1; void module_1() {} ``` test/module2.d: ``` module test.module2; void module_2() {} ``` It produces: ``` $ rdmd reflection.d object std test main -- object module_1 ``` As you see `module_2` wasn't listed. If I change order of import declarations `module_2` will be listed instead of `module_1`. I also tried to create `test/package.d` and publicly import other modules through it, but it behave in the same way. So, how to reflect on imported packages? [0]: http://youtu.be/xpImt14KTdc?t=42m26s
Re: package reflection
On 2014-06-22 14:11:58 +, sigod said: In the video Case Studies In Simplifying Code With Compile-Time Reflection [was pointed out][0] that it is possible to reflect on imported packages. So, I tried: reflection.d: ``` import std.stdio; import test.module1; import test.module2; void main() { foreach (m; __traits(allMembers, mixin(__MODULE__))) { writeln(m); } writeln(--); foreach (m; __traits(allMembers, test)) { writeln(m); } } ``` test/module1.d: ``` module test.module1; void module_1() {} ``` test/module2.d: ``` module test.module2; void module_2() {} ``` It produces: ``` $ rdmd reflection.d object std test main -- object module_1 ``` As you see `module_2` wasn't listed. If I change order of import declarations `module_2` will be listed instead of `module_1`. I also tried to create `test/package.d` and publicly import other modules through it, but it behave in the same way. So, how to reflect on imported packages? [0]: http://youtu.be/xpImt14KTdc?t=42m26s This is very frustrating indeed, and I have an open bug request about it. Please bump it so it gets some attention: https://issues.dlang.org/show_bug.cgi?id=11595 -Shammah
Class Data Members Name Reflection
Is there a way to iterate over the symbolic names of the data members of a class instance? I'm currently using .tupleof to get its values (and in turn types) to implement pretty printing to multiple backends (currently testing HTML) using as much of D's compile time reflection as possible: https://github.com/nordlow/justd/blob/master/pprint.d I've currently defined mappings from InputRanges of Aggregates (tuples, structs, and classes) to HTML tables where - the aggregate members are mapped to table columns (and their types in turn two column headers) and - range elements to rows and I would like to perfect the output by also propagating the member names to the column headings. I'm aware of __traits(allMembers, Type) but those return more than .tupleof does. Help please.
Re: Class Data Members Name Reflection
Two options: do allMembers and filter it out to only be data members, or do some slicing of tupleof.stringof: S s; foreach(idx, member; s.tupleof) { writeln(Name: , s.tupleof[idx].stringof[2..$]); } The tupleof[idx] inside the loop is important instead of just using member because then you get the name, then the slicing is because you get: s.foo for example, and you want to slice off the s. to leave just the name.
Re: Class Data Members Name Reflection
On Tuesday, 10 June 2014 at 16:13:31 UTC, Adam D. Ruppe wrote: Two options: do allMembers and filter it out to only be data members, or do some slicing of tupleof.stringof: What trait should I use to filter out data members? S s; foreach(idx, member; s.tupleof) { writeln(Name: , s.tupleof[idx].stringof[2..$]); } Ok. I tried foreach (ix, memb; arg.args[0].front.tupleof) { import std.stdio: writeln; writeln(arg.args[0].front.tupleof[ix].stringof); } Almost there...except that the print seems to verbose and bit funny: ref FKind __tup4778 = front(arg._args_field_0); , __tup4778.kindName ref FKind __tup4779 = front(arg._args_field_0); , __tup4779.description ref FKind __tup4780 = front(arg._args_field_0); , __tup4780.wikiURL ref FKind __tup4781 = front(arg._args_field_0); Did I do something wrong?
Re: Class Data Members Name Reflection
On Tuesday, 10 June 2014 at 16:30:52 UTC, Nordlöw wrote: What trait should I use to filter out data members? No trait, more like an is thing to see if the thing has an init. I think static if(is(typeof(__traits(getMember, Thing, name).init)) { } will do it. (BTW the sample chapter of my book talks about reflection, I think I talked about some of this in there: http://www.packtpub.com/discover-advantages-of-programming-in-d-cookbook/book ) foreach (ix, memb; arg.args[0].front.tupleof) Eeek, I actually used s for a reason there - it gives you a simple name that is easily repeated and filtered. The nasty string you're seeing is the name of a compiler-generated temporary variable in the foreach. That said, your field names are in there at the end, so another option would be to run it through lastIndexOf(.) and then slice to that. So it works backward to the dot and slices off the rest of the string. string s = arg.args[0].front.tupleof[idx].stringof; auto dotIndex = s.lastIndexOf(.); assert(dotIndex = 0); // it ought to be there anyway auto name = s[dotIndex + 1 .. $]; // slice off the temp name, whatever it is
Re: Class Data Members Name Reflection
On Tuesday, 10 June 2014 at 16:10:09 UTC, Nordlöw wrote: Is there a way to iterate over the symbolic names of the data members of a class instance? I'm currently using .tupleof to get its values (and in turn types) to implement pretty printing to multiple backends (currently testing HTML) using as much of D's compile time reflection as possible: https://github.com/nordlow/justd/blob/master/pprint.d I've currently defined mappings from InputRanges of Aggregates (tuples, structs, and classes) to HTML tables where - the aggregate members are mapped to table columns (and their types in turn two column headers) and - range elements to rows and I would like to perfect the output by also propagating the member names to the column headings. I'm aware of __traits(allMembers, Type) but those return more than .tupleof does. Help please. I am not sure I understand the question. Does this help? struct A { int x; double y; } void main() { foreach (idx, elem; A.init.tupleof) { pragma(msg, __traits(identifier, A.tupleof[idx])); } } // output: // x // y
Re: Class Data Members Name Reflection
I am not sure I understand the question. Does this help? struct A { int x; double y; } void main() { foreach (idx, elem; A.init.tupleof) { pragma(msg, __traits(identifier, A.tupleof[idx])); } } // output: // x // y Exactly what I wanted! BTW: Can DMD serve use file and line location of user defined type aswell? Thx!
Re: Class Data Members Name Reflection
BTW: Can DMD serve use file and line location of user defined type aswell? Thx! Correction: I mean serve *us*
Re: Class Data Members Name Reflection
On Tuesday, 10 June 2014 at 17:29:35 UTC, Dicebot wrote: On Tuesday, 10 June 2014 at 16:10:09 UTC, Nordlöw wrote: Is there a way to iterate over the symbolic names of the data members of a class instance? I'm currently using .tupleof to get its values (and in turn types) to implement pretty printing to multiple backends (currently testing HTML) using as much of D's compile time reflection as possible: https://github.com/nordlow/justd/blob/master/pprint.d I've currently defined mappings from InputRanges of Aggregates (tuples, structs, and classes) to HTML tables where - the aggregate members are mapped to table columns (and their types in turn two column headers) and - range elements to rows and I would like to perfect the output by also propagating the member names to the column headings. I'm aware of __traits(allMembers, Type) but those return more than .tupleof does. Help please. I am not sure I understand the question. Does this help? struct A { int x; double y; } void main() { foreach (idx, elem; A.init.tupleof) { pragma(msg, __traits(identifier, A.tupleof[idx])); } } // output: // x // y Notice that A.init.tupleof segfaults for classes so that is _not_ an adviced solution in a generic solution! But fortunately I always have an instance, say a, of A available in the pprint functions so I just use a.tupleof instead! Now it works! I'll update pprint.d later today! I'll further extract away the dumb dependencies for pprint.d in the upcoming days so it can be reused later on. Thanks you all!
Re: Class Data Members Name Reflection
On Tuesday, 10 June 2014 at 16:13:31 UTC, Adam D. Ruppe wrote: Two options: do allMembers and filter it out to only be data members, or do some slicing of tupleof.stringof: S s; foreach(idx, member; s.tupleof) { writeln(Name: , s.tupleof[idx].stringof[2..$]); } The tupleof[idx] inside the loop is important instead of just using member because then you get the name, then the slicing is because you get: s.foo for example, and you want to slice off the s. to leave just the name. You may not want to use stringof for this, because stringof is explicitly defined as being able to change across versions, and no actual format is defined. Instead use __traits(identifier, s.tupleof[idx]). Also note that .tupleof will not return static fields.
Re: Class Data Members Name Reflection
On Tuesday, 10 June 2014 at 20:01:37 UTC, Nordlöw wrote: Notice that A.init.tupleof segfaults for classes so that is _not_ an adviced solution in a generic solution! There's no need to use .init: import std.stdio; struct Foo { int a, b; } void main() { writeln(__traits(identifier, Foo.tupleof[0])); }
DMD fail when using both reflection and UDA
DMD (dmdfe 2.066) fail when i use UDA which store a delegate code below works if i remove @section UDA otheswise it give this error: dmd: statement.c:714: ErrorStatement::ErrorStatement(): Assertion `global.gaggedErrors || global.errors' failed. is a bug ? --- CODE also on dpaste http://dpaste.dzfl.pl/3a3d660bd3bc import std.stdio; import std.typecons : Tuple; import std.typetuple : Filter; struct attribute{} @attribute struct section( alias start, alias end) { alias checkStart = start; alias checkEnd = end; } template hasSection(T) { static bool helper() { foreach(memberName; __traits(allMembers, T)) { foreach(attr; __traits(getAttributes, __traits(getMember, T, memberName))) { static if(is(attr == Section)) return true; } } return false; } enum hasSection = helper(); } struct Data{ @section!( ( words ) = words[0] == '@' , ( words ) = words[0] == '\n' ) string a; @section!( ( words ) = words[0] 63 words[0] 115 , ( words ) = words[0] == '\n' ) string b; @section!( ( words ) = words[0] == '+' , ( words ) = words[0] == '\n' ) string c; } template toTuple(T){ static string maker(){ string statement = alias toTuple = Tuple!(; foreach(const memberName; __traits(allMembers, T)){ //~ mixin(`alias f = Filter!(hasSection, __traits(getAttributes, T.` ~ memberName ~ `));`); statement ~= typeof(__traits(getMember, T, memberName)).stringof ~ ,\ ~ memberName ~ \, ; } statement = statement[0..$-2] ~ ) ; ; // $-2 to remove extra comma return statement; } mixin( maker() ); } void main() { alias A = toTuple!Data; A a; a[0] = 1; a.x = 1; }
Re: DMD fail when using both reflection and UDA
On Sunday, 1 June 2014 at 16:02:47 UTC, bioinfornatics wrote: DMD (dmdfe 2.066) fail when i use UDA which store a delegate code below works if i remove @section UDA otheswise it give this error: dmd: statement.c:714: ErrorStatement::ErrorStatement(): Assertion `global.gaggedErrors || global.errors' failed. is a bug ? --- CODE also on dpaste http://dpaste.dzfl.pl/3a3d660bd3bc import std.stdio; import std.typecons : Tuple; import std.typetuple : Filter; struct attribute{} @attribute struct section( alias start, alias end) { alias checkStart = start; alias checkEnd = end; } template hasSection(T) { static bool helper() { foreach(memberName; __traits(allMembers, T)) { foreach(attr; __traits(getAttributes, __traits(getMember, T, memberName))) { static if(is(attr == Section)) return true; } } return false; } enum hasSection = helper(); } struct Data{ @section!( ( words ) = words[0] == '@' , ( words ) = words[0] == '\n' ) string a; @section!( ( words ) = words[0] 63 words[0] 115 , ( words ) = words[0] == '\n' ) string b; @section!( ( words ) = words[0] == '+' , ( words ) = words[0] == '\n' ) string c; } template toTuple(T){ static string maker(){ string statement = alias toTuple = Tuple!(; foreach(const memberName; __traits(allMembers, T)){ //~ mixin(`alias f = Filter!(hasSection, __traits(getAttributes, T.` ~ memberName ~ `));`); statement ~= typeof(__traits(getMember, T, memberName)).stringof ~ ,\ ~ memberName ~ \, ; } statement = statement[0..$-2] ~ ) ; ; // $-2 to remove extra comma return statement; } mixin( maker() ); } void main() { alias A = toTuple!Data; A a; a[0] = 1; a.x = 1; } ok it seem problem from my code a type string i need to understand why
Re: DMD fail when using both reflection and UDA
stupid me bug was at the end a[0] = 1; become a[0] = 1; but error error was so stnange to me i though that was a bug
Re: DMD fail when using both reflection and UDA
In any case, it's an internal compiler error, so it's a bug. Users should never see ICEs. Could you please report it, with the entire error message?
Re: DMD fail when using both reflection and UDA
On Sunday, 1 June 2014 at 16:18:45 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: In any case, it's an internal compiler error, so it's a bug. Users should never see ICEs. Could you please report it, with the entire error message? Ok thanks is don at https://issues.dlang.org/show_bug.cgi?id=12838
Re: templates, enums, CT reflection: compiler bug or not?
no one any ideas? well, i filed two bug reports for now: https://d.puremagic.com/issues/show_bug.cgi?id=12532 https://d.puremagic.com/issues/show_bug.cgi?id=12533
Re: Does D have reflection?
On Sunday, 6 April 2014 at 02:25:32 UTC, dnspies wrote: For instance, could I write a generic function to reconstruct any object of any type from a JSON object? Yes, you can use __traits(allMembers) at compile time to build a runtime function that does the setting. .tupleof can do it too, which is what I used in the fromUrlParam function in my web.d that populates a struct from an associative array of runtime strings: https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/web.d#L2507
templates, enums, CT reflection: compiler bug or not?
i stumbled upon something strange while wondering around meta/codegen-lands. it took me almost a week to reduce it to the following test case. i have no clue what is going on, whether i have entered bug territory or just encountered my own limitations mind you, i have 2 issues with the code: (1) that my template, which uses __traits(compiles, ...), under certain circumstances (aka 'if things are getting complicated') fails to see symbols that one could argue are valid in this scope. (annoying maybe, but not my main problem) (2) the strange compiler error i get when using the template on itself, but only if it is not the first time that the instantiation is used. this is my real issue cause i don't know how to work around this. during my attempts to reduce this, starting from much more complicated code, i encountered all sorts of errors, including ICE and __error stuff. so am i being stupid or is it a compiler bug? cheers, det ===CODE=== module demo; template valid(string mem){ pragma(msg, instantiation of valid with: ~mem); static if( !__traits( compiles, mixin(mem) ) ){ enum valid = false; }else{ enum valid = true; } } enum ok = valid!foo; pragma(msg, ok ); // - true // fine, recognizes 'foo' in module scope enum works = valid!fails; pragma(msg, works );// - false // problematic, fails to see 'fails' in module scope enum dummy = valid!fails; pragma(msg, dummy );// - false // same behavior, as long as you are not testing yourself enum fails = valid!fails; // Error: variable demo.fails had semantic errors when compiling // NOTE: if you comment out the first two usages of valid!fails, it will work here, // although it will result in false // pragma(msg, fails ); enum foo = 42; void main(){}
Re: reflection over templates
On Wednesday, 19 March 2014 at 16:18:17 UTC, Andrej Mitrovic wrote: And after we determine it is a template, can we extract the required arguments list like we can with a regular function at all? Well there's TemplateArgsOf for *instantiations*, but I'm not sure how one would do it with non-instantiations. In particular how would we create a tuple of template parameter types where one of the parameters was an alias? E.g.: template Foo(int, alias X); alias Args = TypeTuple!(int, ???); There is no alias type you could use in this case. One can use value instead of a type, like alias.
Re: reflection over templates
As a workaround one can use set of relevant trait checks: 1) type is void 2) is not a variable or callable 3) .stringof fits NAME(ARGS) pattern
Re: reflection over templates
Wait just a bit more https://github.com/D-Programming-Language/dmd/pull/3380 :)
Re: reflection over templates
On Wednesday, 19 March 2014 at 16:10:52 UTC, Dicebot wrote: Wait just a bit more https://github.com/D-Programming-Language/dmd/pull/3380 :) megarox. Make it so.
reflection over templates
Given: template Foo(string T) { enum Foo = to!int(T); } (or anything else, really) Is there anything we can do with static if to identify it as a template? I tried: static if(is(Foo == template)) {} // nope, basic type expected, not template Note that is(typeof(Foo) == function) {} is how we check for regular functions. static if(is(typeof(Foo) == template)) {} // nope In fact, typeof(Foo) == void... is that something we can use? I know we can break down a template instantiation with one of the arcane is expressions, but I don't have that here, I just want to identify the template Foo as a template. This is in the context of doing __traits(allMembers) over a module and trying to categorize every member. Checking for a void type seems to be the closest I've gotten, but that seems awfully strange. I guess other variables can't be declared with type void, so maybe that is a unique differentiator, but still, idk about it. And after we determine it is a template, can we extract the required arguments list like we can with a regular function at all?
Re: reflection over templates
On 3/19/14, Adam D. Ruppe destructiona...@gmail.com wrote: Is there anything we can do with static if to identify it as a template? https://github.com/D-Programming-Language/dmd/pull/3380 And after we determine it is a template, can we extract the required arguments list like we can with a regular function at all? Well there's TemplateArgsOf for *instantiations*, but I'm not sure how one would do it with non-instantiations. In particular how would we create a tuple of template parameter types where one of the parameters was an alias? E.g.: template Foo(int, alias X); alias Args = TypeTuple!(int, ???); There is no alias type you could use in this case.
Re: reflection over templates
On 03/19/2014 05:34 PM, Adam D. Ruppe wrote: On Wednesday, 19 March 2014 at 16:10:52 UTC, Dicebot wrote: Wait just a bit more https://github.com/D-Programming-Language/dmd/pull/3380 :) megarox. Make it so. Nice. I have some ugly hacks that's probably full of bugs for this (look at the bottom): template isLValue(T) { enum isLValue = false; } /// ditto template isLValue(alias T) { enum isLValue = !isType!T isAddressable!T __traits(compiles, { Unqual!(TypeOf!T) t = TypeOf!(T).init; }); } /// ditto template isRValue(T) { enum isRValue = false; } /// ditto template isRValue(alias T) { static if(isType!T) enum isRValue = false; else enum isRValue = __traits(compiles, { typeof(T) t = T; }) !isAddressable!T; } template isValue(T) { enum isValue = false; } /// ditto template isValue(alias T) { enum isValue = isLValue!T || isRValue!T; } /// ditto template isType(T) { enum isType = is(T); } /// ditto template isType(alias T) { enum isType = is(T) || isCallable!T; } template isTemplate(T) { enum isTemplate = !(isValue!T || isType!T); } template isTemplate(alias T) { enum isTemplate = !(isValue!T || isType!T); }
DLL's reflection and Exceptions
Hello everyone! I'm currently working on a run-time reflection module. The intent of this module is to simplify the process of loading functions / classes / structs from DLL's loaded at run-time. It works something like this ATM: //In pluggin.d (A dll module) void foo() { ... } class Bar { ... } struct Baz { ... } ... more members At the end of the file i have a function like this export extern(C) MetaAssembly getMetaAssembly() { //Tuple of filters to only load relevant stuff. alias filters = standardFilters; return AssemblyGenerator!(filters, module1, ..., moduleN).data; } //In program.d (A host program) void main() { auto dll = loadDll(pluggin0.dll); MetaAssembly assembly = dll.func!(getter_t)(getMetaAssembly)() //Use assembly to find some classes //construct them and invoke some methods. MetaClass c = assembly. classes. find!(x = x.name == Foo)[0]; RTObject fooObj = c.constructors[0].create(); MetaMethod method = c.methods[0]; method.invoke(fooObj, Hello); } AssemblyGenerator!(...) extracts all needed information from the modules and stores them in a collection of structs that can be used at run-time to do stuff like create instances / set fields / check attributes. Normal reflection stuff. This works fine for normal code flow. However it all falls apart as soon as any function located in a DLL throws an exception. If an exception is thrown the application freezes, usually visual studio crashes with First hand exception: Privileged Instruction (some address). I have hacked my way around this limitation like so: //pluggin.d alias exception_handler_t = void function(Throwable) nothrow; __gshared exception_handler_t exceptionHandler; //program.d Throwable t = null; void exceptionHandler(Throwable thrown) nothrow { t = thrown; } bool exceptionThrown() { return t !is null; } void rethrowException() { DLLException e = new DLLException(t.toString()); t = null; throw e; } void main() { auto dll = loadDLL(pluggin0.dll); MetaAssembly assembly = dll.func!(getter_t)(getMetaAssembly)() auto field = assembly. staticFields. find!(x = x.name == exceptionHandler); field.set(exceptionHandler) } The reflection api wrapps all functions / methods with a try - catch that will call the exceptionHandler if an exception occurs. At the calle side (program.a) after every call it will check if an exception was thrown and if so rethrowng it as a DLLException. This workaround works, (atleast for now) but i don't like it. It complicates the low-level reflection api alot and it only solves the problem of calls from program.d to pluggin.d not the other way around (unless i wrap them aswell). So now to the questions. 1. Why can't i throw exceptions over a DLL boundary? 2. Are there any problems with my hack other then the ones already stated? 3. Does other workarounds exist? Thank you for your time!
Re: Is it possible using reflection or similar to extract only public method names from classes?
On 2013-08-07 00:57, Marek Janukowicz wrote: See traits: http://dlang.org/traits.html Look for: getProtection, getVirtualFunctions, getVirtualMethods. And allMembers and derivedMembers. -- /Jacob Carlborg
Re: Is it possible using reflection or similar to extract only public method names from classes?
On Tuesday, 6 August 2013 at 22:55:49 UTC, Marek Janukowicz wrote: Gary Willoughby wrote: Is it possible using reflection or similar to extract only public method names from classes? I'm thinking how i would go about writing a unit test/mocking framework, investigating how i can gather information about such things before i manipulate them. See traits: http://dlang.org/traits.html Look for: getProtection, getVirtualFunctions, getVirtualMethods. I thought using __traits(...) was frowned upon?
Re: Is it possible using reflection or similar to extract only public method names from classes?
On Wednesday, 7 August 2013 at 11:47:27 UTC, Gary Willoughby wrote: I thought using __traits(...) was frowned upon? They want to give them phobos wrappers that might be a little prettier, but other than beauty/ugliness there's no reason not to use it.
Is it possible using reflection or similar to extract only public method names from classes?
Is it possible using reflection or similar to extract only public method names from classes? I'm thinking how i would go about writing a unit test/mocking framework, investigating how i can gather information about such things before i manipulate them.
Re: Is it possible using reflection or similar to extract only public method names from classes?
Gary Willoughby wrote: Is it possible using reflection or similar to extract only public method names from classes? I'm thinking how i would go about writing a unit test/mocking framework, investigating how i can gather information about such things before i manipulate them. See traits: http://dlang.org/traits.html Look for: getProtection, getVirtualFunctions, getVirtualMethods. -- Marek Janukowicz
Re: Is it possible using reflection or similar to extract only public method names from classes?
On Tue, Aug 06, 2013 at 11:41:35PM +0200, Gary Willoughby wrote: Is it possible using reflection or similar to extract only public method names from classes? I'm thinking how i would go about writing a unit test/mocking framework, investigating how i can gather information about such things before i manipulate them. The following code demonstrates how you can do this: import std.stdio; class Base { private int x; public int y; this() {} private void privMethod() {} public void method() {} } class Derived : Base { public override void method() {} public void derivedMethod() {} private void privDerivedMethod() {} } void showAllMethods(C)(C obj) { writeln(All members:); foreach (field; __traits(allMembers, C)) { static if (is(typeof(__traits(getMember, obj, field)) T == function)) { auto prot = __traits(getProtection, __traits(getMember, obj, field)); writefln(\t(%s) %s, prot, field); } } } void showDerivedMethods(C)(C obj) { writeln(\nDerived members:); foreach (field; __traits(derivedMembers, C)) { static if (is(typeof(__traits(getMember, obj, field)) T == function)) { auto prot = __traits(getProtection, __traits(getMember, obj, field)); writefln(\t(%s) %s, prot, field); } } } string[] getPublicMethods(C)(C obj) { string[] methods; foreach (field; __traits(allMembers, C)) { static if (is(typeof(__traits(getMember, obj, field)) == function) __traits(getProtection, __traits(getMember, obj, field)) == public) { methods ~= field; } } return methods; } void main() { auto d = new Derived(); showAllMethods(d); showDerivedMethods(d); writeln(All public methods:); writeln(getPublicMethods(d)); } The output is: All members: (public) method (public) derivedMethod (private) privDerivedMethod (public) __ctor (private) privMethod (public) toString (public) toHash (public) opCmp (public) opEquals (public) factory Derived members: (public) method (public) derivedMethod (private) privDerivedMethod (public) __ctor All public methods: [method, derivedMethod, __ctor, toString, toHash, opCmp, opEquals, factory] Hope this helps! T -- Designer clothes: how to cover less by paying more.
Derived classes? Reflection
Currently is there a way to get all of the subclasses of a class at compile time? It seems like something that should be possible using traits but I can't seems to see how. Something like class A{...} class B:A{...} class C:A{...} ... foreach(auto t ; getsubclass(A)) { ... } Any help would be grateful. Tofu
Re: Derived classes? Reflection
On 4/13/13, Tofu Ninja emmo...@purdue.edu wrote: Currently is there a way to get all of the subclasses of a class at compile time? There might be things like using .moduleinfo and traversing imports to find all classes, but I think separate compilation makes this unreliable. There is however BaseClassTuple in std.traits, so you can pass a leaf class to get the class hierarchy.
Re: Derived classes? Reflection
On Saturday, 13 April 2013 at 16:16:03 UTC, Tofu Ninja wrote: Currently is there a way to get all of the subclasses of a class at compile time? It seems like something that should be possible using traits but I can't seems to see how. Something like class A{...} class B:A{...} class C:A{...} ... foreach(auto t ; getsubclass(A)) { ... } Any help would be grateful. Tofu Maybe this is helpfully: http://forum.dlang.org/thread/scgjnudclnwlbdqqd...@forum.dlang.org
Re: Derived classes? Reflection
Maybe this is helpfully: http://forum.dlang.org/thread/scgjnudclnwlbdqqd...@forum.dlang.org Oddly enough, I found that at about the same time you posted it.
Re: Derived classes? Reflection
On Saturday, 13 April 2013 at 17:45:12 UTC, Tofu Ninja wrote: Maybe this is helpfully: http://forum.dlang.org/thread/scgjnudclnwlbdqqd...@forum.dlang.org Oddly enough, I found that at about the same time you posted it. Sadly this does not provide a compile time solution, only runtime.
Re: question with compile-time reflection
template NDimensionalArrayType(T,alias size) I'm wondering what alias size does? I can't find that form documented anywhere, but it seems to be valid. Thanks. --rt
Re: question with compile-time reflection
And since alias can represent any symbol,i think that it's correct usage.
Re: question with compile-time reflection
On Monday, 11 March 2013 at 00:10:46 UTC, Rob T wrote: template NDimensionalArrayType(T,alias size) I'm wondering what alias size does? I can't find that form documented anywhere, but it seems to be valid. Thanks. --rt It's just a little hack for known bug - only string and integer value can be passed into template. size is array,and it's really size of n-dimensional array,every element matches its dimension.
Re: question with compile-time reflection
On Monday, 11 March 2013 at 00:10:46 UTC, Rob T wrote: template NDimensionalArrayType(T,alias size) I'm wondering what alias size does? I can't find that form documented anywhere, but it seems to be valid. http://dlang.org/template.html#TemplateAliasParameter
Re: question with compile-time reflection
On Monday, 11 March 2013 at 00:26:25 UTC, anonymous wrote: On Monday, 11 March 2013 at 00:10:46 UTC, Rob T wrote: template NDimensionalArrayType(T,alias size) I'm wondering what alias size does? I can't find that form documented anywhere, but it seems to be valid. http://dlang.org/template.html#TemplateAliasParameter I actually read that page, but somehow missed this description or more likely did not understand what it meant. I think I could spend 10 years reading up on D and still not fully know everything about it. --rt
question with compile-time reflection
Hi! this code fails with message:NDimensionalArray.doIndex(Array) if (is(Array _ : NDimensionalArrayType!(T,s),const(int[]) s)) cannot deduce template function from argument types !()(int[2u][2u],const(int[])) Tell me please,am I wrong? And if yes,what should I change to make it work? template NDimensionalArrayType(T,alias size) if(is(typeof(size) _ : const int[]) size.length 0) { static if(size.length 1) alias NDimensionalArrayType!(T,size[1..$])[size[0]] NDimensionalArrayType; else alias T[size[0]] NDimensionalArrayType; } struct NDimensionalArray(T,alias size) { private NDimensionalArrayType!(T,size) m_array; static ref T doIndex(Array)(Array array,const int[] index) //HERE if(is(Array _ : NDimensionalArrayType!(T,s),const int[] s)) { assert(index.length == s.length); if(index.length == 1) return array[index[0]]; else return doIndex(array[index[0]],index[1..$]); } ref T opIndex(const int[] index) { return doIndex(m_array,index); } alias m_array this; } void main() { NDimensionalArray!(int,[2,2]) array; }
Re: question with compile-time reflection
template NDimensionalArrayType(T,alias size) I think your use of alias size is incorrect. See http://dlang.org/declaration.html --rt
Re: question with compile-time reflection
this code fails with message:NDimensionalArray.doIndex(Array) if (is(Array _ : NDimensionalArrayType!(T,s),const(int[]) s)) cannot deduce template function from argument types !()(int[2u][2u],const(int[])) Tell me please,am I wrong? And if yes,what should I change to make it work? I'm no D expert, but here's what I got. 1. One problem is returning the wrong type from doIndex. When the condition if(index.length == 1) is false, the subsequent line is still compiled but fails to return a ref T since array[index[0]] is an array of T, not a T. The correct way (and better for performance, too) would be a compile-time static if there, like in the code below. (I don't quite get the syntax of the template constraint for doIndex, so I've just commented that out for now.) 2. The next problem is that fixed-size arrays obey value semantics, so they should be passed by reference and not by value. Here's what works for me (DMD 2.062): - import std.stdio; template NDimensionalArrayType(T,alias size) if(is(typeof(size) _ : const int[]) size.length 0) { static if(size.length 1) alias NDimensionalArrayType!(T,size[1..$])[size[0]] NDimensionalArrayType; else alias T[size[0]] NDimensionalArrayType; } struct NDimensionalArray(T,alias size) { private NDimensionalArrayType!(T,size) m_array; static ref T doIndex(Array)(ref Array array,const int[] index) //HERE // if(is(Array _ : NDimensionalArrayType!(T,s),const int[] s)) { // assert(index.length == s.length); assert(index.length = size.length); debug {writefln(doIndex (%s, %s = %s), typeof(array).stringof, typeof(index).stringof, index);} static if(is(Array : T[])) { assert(index.length == 1); return array[index[0]]; } else { assert(index.length 1); return doIndex(array[index[0]],index[1..$]); } } ref T opIndex(const int[] index) { return doIndex(m_array,index); } alias m_array this; } void main() { NDimensionalArray!(int,[5,2]) array; array[[4,1]] = 1; assert(array[[4,1]] == 1); } - With the debug mode on, it successfully prints the following: - doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) - On a side note, this still looks like too much effort to do one opIndex in terms of performance. I doubt that any current compiler would optimize all that into a simple multiply + bounds-check + add loop. - Ivan Kazmenko.
Re: question with compile-time reflection
On Saturday, 9 March 2013 at 23:05:56 UTC, Ivan Kazmenko wrote: this code fails with message:NDimensionalArray.doIndex(Array) if (is(Array _ : NDimensionalArrayType!(T,s),const(int[]) s)) cannot deduce template function from argument types !()(int[2u][2u],const(int[])) Tell me please,am I wrong? And if yes,what should I change to make it work? I'm no D expert, but here's what I got. 1. One problem is returning the wrong type from doIndex. When the condition if(index.length == 1) is false, the subsequent line is still compiled but fails to return a ref T since array[index[0]] is an array of T, not a T. The correct way (and better for performance, too) would be a compile-time static if there, like in the code below. (I don't quite get the syntax of the template constraint for doIndex, so I've just commented that out for now.) 2. The next problem is that fixed-size arrays obey value semantics, so they should be passed by reference and not by value. Here's what works for me (DMD 2.062): - import std.stdio; template NDimensionalArrayType(T,alias size) if(is(typeof(size) _ : const int[]) size.length 0) { static if(size.length 1) alias NDimensionalArrayType!(T,size[1..$])[size[0]] NDimensionalArrayType; else alias T[size[0]] NDimensionalArrayType; } struct NDimensionalArray(T,alias size) { private NDimensionalArrayType!(T,size) m_array; static ref T doIndex(Array)(ref Array array,const int[] index) //HERE // if(is(Array _ : NDimensionalArrayType!(T,s),const int[] s)) { // assert(index.length == s.length); assert(index.length = size.length); debug {writefln(doIndex (%s, %s = %s), typeof(array).stringof, typeof(index).stringof, index);} static if(is(Array : T[])) { assert(index.length == 1); return array[index[0]]; } else { assert(index.length 1); return doIndex(array[index[0]],index[1..$]); } } ref T opIndex(const int[] index) { return doIndex(m_array,index); } alias m_array this; } void main() { NDimensionalArray!(int,[5,2]) array; array[[4,1]] = 1; assert(array[[4,1]] == 1); } - With the debug mode on, it successfully prints the following: - doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) - On a side note, this still looks like too much effort to do one opIndex in terms of performance. I doubt that any current compiler would optimize all that into a simple multiply + bounds-check + add loop. - Ivan Kazmenko. Thank you very much for your time) Your answer is very useful.