Thread overview
Getting nice print of struct for debugging
Feb 20, 2017
Paul Backus
Feb 21, 2017
Jacob Carlborg
Feb 24, 2017
Jacob Carlborg
Feb 25, 2017
Minty Fresh
Feb 25, 2017
Minty Fresh
February 20, 2017
Hello,
I have a little program where I am filling a struct with values from an regex match.
Now I want to display the content of the struct for debugging purpose.

If struct is named MyStruct

I can print a list of the field names with:

foreach(fieldname;FieldNameTuple!MyStruct){writef("%s ",fieldname);}
	
If myvar is of type MyStruct how can I make a table like:

fieldname_1: value_1
fieldname_2: value_2
.
.
fieldname_n: value_n

Is there a way to do this with a single expression in D.

Similar to a ruby call myvar.send(fieldname) to get the value from fieldname inside a loop?
write(myvar); sure is working directly but I want to get the field names displayed, too.

(A work around might be work with the format("%s",myvar) string and extract the values with an index?)

Regards mt.

February 20, 2017
On Monday, 20 February 2017 at 16:04:17 UTC, Martin Tschierschke wrote:
> Hello,
> I have a little program where I am filling a struct with values from an regex match.
> Now I want to display the content of the struct for debugging purpose.

I believe the easiest way to do this is to define a custom toString member function for your struct. For example:

struct MyStruct {
    int x;
    double y;
    string s;

    string toString() {
        import std.format: format;

        return "MyStruct(x: %d, y: %f, s: \"%s\")".format(x, y, s);
    }
}

void main() {
    import std.stdio: writeln;

    MyStruct foo;
    foo.x =2; foo.y = 3.14; foo.s = "the quick brown fox";

    writeln(foo); // Prints MyStruct(x: 2, y: 3.140000, s: "the quick brown fox")
}

February 20, 2017
On Monday, 20 February 2017 at 16:18:58 UTC, Paul Backus wrote:
> On Monday, 20 February 2017 at 16:04:17 UTC, Martin Tschierschke wrote:
>> Hello,
>> I have a little program where I am filling a struct with values from an regex match.
>> Now I want to display the content of the struct for debugging purpose.
>
> I believe the easiest way to do this is to define a custom toString member function for your struct. For example:
>
> struct MyStruct {
>     int x;
>     double y;
>     string s;
>
>     string toString() {
>         import std.format: format;
>
>         return "MyStruct(x: %d, y: %f, s: \"%s\")".format(x, y, s);
>     }
> }
>
> void main() {
>     import std.stdio: writeln;
>
>     MyStruct foo;
>     foo.x =2; foo.y = 3.14; foo.s = "the quick brown fox";
>
>     writeln(foo); // Prints MyStruct(x: 2, y: 3.140000, s: "the quick brown fox")
> }
Good suggestion, thank you! Then the definition is near the struct definition and I do not need to care about what to call, just writeln(myvar); cool!


February 21, 2017
On 2017-02-20 17:04, Martin Tschierschke wrote:
> Hello,
> I have a little program where I am filling a struct with values from an
> regex match.
> Now I want to display the content of the struct for debugging purpose.
>
> If struct is named MyStruct
>
> I can print a list of the field names with:
>
> foreach(fieldname;FieldNameTuple!MyStruct){writef("%s ",fieldname);}
>
> If myvar is of type MyStruct how can I make a table like:
>
> fieldname_1: value_1
> fieldname_2: value_2
> .
> .
> fieldname_n: value_n
>
> Is there a way to do this with a single expression in D.
>
> Similar to a ruby call myvar.send(fieldname) to get the value from
> fieldname inside a loop?
> write(myvar); sure is working directly but I want to get the field names
> displayed, too.
>
> (A work around might be work with the format("%s",myvar) string and
> extract the values with an index?)

Yes, this works, I would say this is the simplest:

MyStruct s;

foreach (index, name ; FieldNameTuple!MyStruct)
    writefln("%s: %s", name, s.tupleof[index]);

If you want something more close to "send" in Ruby, you need to use a string mixin, like this:

foreach (name ; FieldNameTuple!MyStruct)
    writefln("%s: %s", name, mixin("s." ~ name));

The string mixin example works for methods, opDispatch and similar as well. The tupleof example, the first one, works only for fields.

-- 
/Jacob Carlborg
February 22, 2017
On Tuesday, 21 February 2017 at 14:02:54 UTC, Jacob Carlborg wrote:
[...]
> Yes, this works, I would say this is the simplest:
>
> MyStruct s;
>
> foreach (index, name ; FieldNameTuple!MyStruct)
>     writefln("%s: %s", name, s.tupleof[index]);
>
> If you want something more close to "send" in Ruby, you need to use a string mixin, like this:
>
> foreach (name ; FieldNameTuple!MyStruct)
>     writefln("%s: %s", name, mixin("s." ~ name));
>
> The string mixin example works for methods, opDispatch and similar as well. The tupleof example, the first one, works only for fields.
Exactly what I was looking for, **thank you!**
Both ways of accessing the struct elements are very interesting,
giving an impression what is possible with D.


Is it possible to overwrite "toString" for all structs in one step?

Regards mt.


February 24, 2017
On 2017-02-22 12:18, Martin Tschierschke wrote:

> Exactly what I was looking for, **thank you!**
> Both ways of accessing the struct elements are very interesting,
> giving an impression what is possible with D.
>
>
> Is it possible to overwrite "toString" for all structs in one step?

It depends. You can create a template mixin containing the implementation of toString, which need to be mixed in in all structs. Or you can create a new function that can convert any passed in structs in a generic way. It depends on what you need the string for.

-- 
/Jacob Carlborg
February 25, 2017
On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin Tschierschke wrote:
> On Tuesday, 21 February 2017 at 14:02:54 UTC, Jacob Carlborg wrote:
> [...]
>> Yes, this works, I would say this is the simplest:
>>
>> MyStruct s;
>>
>> foreach (index, name ; FieldNameTuple!MyStruct)
>>     writefln("%s: %s", name, s.tupleof[index]);
>>
>> If you want something more close to "send" in Ruby, you need to use a string mixin, like this:
>>
>> foreach (name ; FieldNameTuple!MyStruct)
>>     writefln("%s: %s", name, mixin("s." ~ name));
>>
>> The string mixin example works for methods, opDispatch and similar as well. The tupleof example, the first one, works only for fields.
> Exactly what I was looking for, **thank you!**
> Both ways of accessing the struct elements are very interesting,
> giving an impression what is possible with D.
>
>
> Is it possible to overwrite "toString" for all structs in one step?
>
> Regards mt.

Since structs are Plain-old Data and don't do inheritance, the best option is a template mixin.

ie.

  template mixin PrettyPrint
  {
      string toString()
      {
          // . . .
      }
  }

From there, you can mix it into any struct you want.

  struct MyStruct
  {
      mixin PrettyPrint;
  }

If you're familiar with Rails, this is similar to a Concern.
February 25, 2017
On Saturday, 25 February 2017 at 01:27:09 UTC, Minty Fresh wrote:
> On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin Tschierschke wrote:
>> [...]
>
> Since structs are Plain-old Data and don't do inheritance, the best option is a template mixin.
>
> ie.
>
>   template mixin PrettyPrint
>   {
>       string toString()
>       {
>           // . . .
>       }
>   }
>
> From there, you can mix it into any struct you want.
>
>   struct MyStruct
>   {
>       mixin PrettyPrint;
>   }
>
> If you're familiar with Rails, this is similar to a Concern.

Errata on that. Should actually be declared as:

  mixin template PrettyPrint()

This is why I shouldn't make posts from my phone.
February 27, 2017
On Saturday, 25 February 2017 at 01:30:09 UTC, Minty Fresh wrote:
> On Saturday, 25 February 2017 at 01:27:09 UTC, Minty Fresh wrote:
>> On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin Tschierschke wrote:
>>> [...]
>>
>> Since structs are Plain-old Data and don't do inheritance, the best option is a template mixin.
>>
>> ie.
>>
>>   template mixin PrettyPrint
>>   {
>>       string toString()
>>       {
>>           // . . .
>>       }
>>   }
>>
>> From there, you can mix it into any struct you want.
>>
>>   struct MyStruct
>>   {
>>       mixin PrettyPrint;
>>   }
>>
>> If you're familiar with Rails, this is similar to a Concern.
>
> Errata on that. Should actually be declared as:
>
>   mixin template PrettyPrint()
>
> This is why I shouldn't make posts from my phone.

Thank you, but this solution from Kevin Brogan, is an good alternative,
to add a special dump function globally, so no need to modify the struct definitions.

https://forum.dlang.org/post/yewavntuyutdvejwjamp@forum.dlang.org

His solution:

import std.traits;

void main()
{
	WSADATA wsa;
	dump!wsa;
}

void dump(alias variable)()
{
	writeln("\nDumping ",typeid(typeof(variable)),":\n");
	writeln(variable.stringof, " = \n{");
	foreach(member; FieldNameTuple!(typeof(variable)))
	{
		writeln("\t", member, ": ", mixin("variable."~member) );
	}
	writeln("}\n");
}