Re: Pretty fields string
On 2/29/12, Andrej Mitrovic wrote: > Just noticed it doesn't work ok if there's a nested template > declaration in a struct. It would say "Error: cannot resolve type for > t.temp(T)". Correction: it was the unittest block that was problematic. I've filed it http://d.puremagic.com/issues/show_bug.cgi?id=7613
Re: Pretty fields string
On 2/29/12, Philippe Sigaud wrote: > Nice. What does it give for: > > - function overloads (PITA that)? > - type aliase (alias int Int;)? > - function aliases or member aliases? > - inner templates (struct template, etc, not pure template as these are not > allowed in a struct)? > - unittests inside the structs? > Well I was mainly interested in printing fields that take memory in a struct/class instance, not functions or other things. :) Just noticed it doesn't work ok if there's a nested template declaration in a struct. It would say "Error: cannot resolve type for t.temp(T)". Then I've tried using a static if + __traits(compiles) to work around it (and even is(typeof)), and before you know it.. Assertion failure: 'type' on line 6695 in file 'expression.c' lol. :p
Re: Pretty fields string
On 2/29/12, Jacob Carlborg wrote: > Seems like what I have in my serialization library Orange: Sweet. I was gonna take a look at Orange for just this purpose. Thanks.
Re: Pretty fields string
On 2012-02-29 10:58, Andrej Mitrovic wrote: I've done this a couple of times before but I always had issues, e.g. functions and property calls would be mixed in. But I think I have a good go-to function now: import std.algorithm; import std.conv; import std.string; import std.stdio; import std.range; struct Foo { int one = 1; @property int test() { return 1; } int three = 3; string[string] aa; string toString() { return prettyFieldsString(this); } } string prettyFieldsString(T)(T t) if (is(T == struct) || is(T == class)) { Appender!string result; Appender!(string[]) fields; Appender!(string[]) values; foreach (member; __traits(allMembers, T)) { mixin(" static if (!is( FunctionTypeOf!(t." ~ member ~ ") )) { static if (member != " ~ `"toString"` ~ ") { fields.put(member); values.put(to!string(__traits(getMember, t, " ~ `"` ~ member ~ `"` ~ "))); } } "); } size_t spaceLen = 1; foreach (field; fields.data) // should use reduce!() here.. spaceLen = max(spaceLen, field.length); alias std.array.replicate replicate; string spaceString = replicate(" ", spaceLen); foreach (field, value; lockstep(fields.data, values.data)) result.put(format("%s: %s%s\n", field, replicate(" ", spaceLen - field.length), value)); return result.data; } void main() { Foo foo; foo.aa["foo"] = "bar"; writeln(foo); } Sample output: http://paste.pocoo.org/show/558492/ I've had to put everything into one foreach loop since there are still some CTFE bugs I run into. I also had to add a check against toString, otherwise I get an infinite loop in the toString() call. Anyway, feel free to use/improve this function. Seems like what I have in my serialization library Orange: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d "fieldsOf" and "getValueOfField". These work only on instance variables and don't care if the variable is public or not. -- /Jacob Carlborg
Re: Pretty fields string
> I've done this a couple of times before but I always had issues, e.g. > functions and property calls would be mixed in. But I think I have a > good go-to function now: Nice. What does it give for: - function overloads (PITA that)? - type aliase (alias int Int;)? - function aliases or member aliases? - inner templates (struct template, etc, not pure template as these are not allowed in a struct)? - unittests inside the structs?
Re: Pretty fields string
Just noticed there's an std.traits import missing. I hate how D silently ignores that FunctionTypeOf is left undefined.
Pretty fields string
I've done this a couple of times before but I always had issues, e.g. functions and property calls would be mixed in. But I think I have a good go-to function now: import std.algorithm; import std.conv; import std.string; import std.stdio; import std.range; struct Foo { int one = 1; @property int test() { return 1; } int three = 3; string[string] aa; string toString() { return prettyFieldsString(this); } } string prettyFieldsString(T)(T t) if (is(T == struct) || is(T == class)) { Appender!string result; Appender!(string[]) fields; Appender!(string[]) values; foreach (member; __traits(allMembers, T)) { mixin(" static if (!is( FunctionTypeOf!(t." ~ member ~ ") )) { static if (member != " ~ `"toString"` ~ ") { fields.put(member); values.put(to!string(__traits(getMember, t, " ~ `"` ~ member ~ `"` ~ "))); } } "); } size_t spaceLen = 1; foreach (field; fields.data) // should use reduce!() here.. spaceLen = max(spaceLen, field.length); alias std.array.replicate replicate; string spaceString = replicate(" ", spaceLen); foreach (field, value; lockstep(fields.data, values.data)) result.put(format("%s: %s%s\n", field, replicate(" ", spaceLen - field.length), value)); return result.data; } void main() { Foo foo; foo.aa["foo"] = "bar"; writeln(foo); } Sample output: http://paste.pocoo.org/show/558492/ I've had to put everything into one foreach loop since there are still some CTFE bugs I run into. I also had to add a check against toString, otherwise I get an infinite loop in the toString() call. Anyway, feel free to use/improve this function.