| Thread overview | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 10, 2014 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. | ||||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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.
| |||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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? | |||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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 | |||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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
| |||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Dicebot | > 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!
| |||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | > BTW: Can DMD serve use file and line location of user defined type aswell?
>
> Thx!
Correction: I mean serve *us*
| |||
June 10, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Dicebot | 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!
| |||
June 11, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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.
| |||
June 11, 2014 Re: Class Data Members Name Reflection | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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]));
}
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply