Issue 9872 - format should include class field values
Summary: format should include class field values
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2013-04-04 00:27 UTC by Andrej Mitrovic
Modified: 2024-12-01 16:17 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2013-04-04 00:27:25 UTC
This is an unfortunate inconsistency:

import std.stdio;
import std.string;

struct S
{
    int x, y;
}

class C
{
    int x, y;
}

void main()
{
    auto s1 = format("%s", S());
    auto s2 = format("%s", new C());

    writeln(s1);  // S(0, 0)
    writeln(s2);  // test.C
}

It forces us to either always define a toString() method or call some custom user-provided formatting function. format() should try to print the values of the class fields if the toString method is not defined.
Comment 1 Andrej Mitrovic 2013-04-04 00:32:34 UTC
Workaround:

private mixin template genToString()
{
    override string toString()
    {
        import std.array;
        import std.conv;
        import std.string;

        Appender!(string[]) result;

        foreach (val; this.tupleof)
        {
            result ~= to!string(val);
        }

        return format("%s(%s)", __traits(identifier, typeof(this)), 
                                result.data.join(", "));
    }
}

class C
{
    int x, y;
    mixin genToString;
}
Comment 2 Andrej Mitrovic 2013-04-04 11:49:19 UTC
How's this for a funky workaround:

diff --git a/std/format.d b/std/format.d
index 8896e38..84169c0 100644
--- a/std/format.d
+++ b/std/format.d
@@ -2512,15 +2512,32 @@ if (is(T == class) && !is(T == enum))
         put(w, "null");
     else
     {
+        Object o = val;     // workaround
+        string delegate() dg = &o.toString;
+
         static if (hasToString!(T, Char) > 1 || (!isInputRange!T && !is(BuiltinTypeOf!T)))
         {
-            formatObject!(Writer, T, Char)(w, val, f);
+            if (dg.funcptr != &Object.toString)
+                formatObject!(Writer, T, Char)(w, val, f);
+            else
+            {
+                enum ident = __traits(identifier, T);
+
+                mixin(format(q{
+                    static struct %s
+                    {
+                        typeof(T.tupleof) fields;
+                    }
+                    %s s;
+                    s.fields = val.tupleof;
+                }, ident, ident));
+
+                formatValue(w, s, f);
+            }
         }
         else
         {
           //string delegate() dg = &val.toString;
-            Object o = val;     // workaround
-            string delegate() dg = &o.toString;
             if (dg.funcptr != &Object.toString) // toString is overridden
             {
                 formatObject(w, val, f);

Yeah it's just a joke. But it works. :P
Comment 3 Infiltrator 2015-12-02 17:18:01 UTC
I like it.  Have you put in a PR yet?
Comment 4 Vladimir Panteleev 2017-07-07 16:43:58 UTC
(In reply to Andrej Mitrovic from comment #2)
> +            if (dg.funcptr != &Object.toString)

Pretty devious. I think it's not unreasonable.
Comment 5 Andrej Mitrovic 2022-07-04 17:09:03 UTC
I think the really consistent part about formatting in Phobos is that the output tends to be semantically-correct syntax.

S(0, 0) is correct as you can construct an instance of `S` this way. But `C(0, 0)` would be semantically incorrect as that's not how classes are constructed. You'd (likely) need to use `new C` and you'd have to care about which constructors are actually implemented, so `new C(0, 0)` might not even be semantically correct either.

Perhaps instead of changing default formatting a better option would be to have a format spec that dumps out the entire representation of the aggregate. "%s" is taken but we could introduce something else.

We could also just close this as WONTFIX.
Comment 6 dlangBugzillaToGithub 2024-12-01 16:17:15 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/9603

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB