Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

format should include class field values #9603

Open
dlangBugzillaToGithub opened this issue Apr 4, 2013 · 5 comments
Open

format should include class field values #9603

dlangBugzillaToGithub opened this issue Apr 4, 2013 · 5 comments

Comments

@dlangBugzillaToGithub
Copy link

andrej.mitrovich (@AndrejMitrovic) reported this on 2013-04-04T00:27:25Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=9872

CC List

  • lt.infiltrator

Description

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.
@dlangBugzillaToGithub
Copy link
Author

andrej.mitrovich (@AndrejMitrovic) commented on 2013-04-04T00:32:34Z

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;
}

@dlangBugzillaToGithub
Copy link
Author

andrej.mitrovich (@AndrejMitrovic) commented on 2013-04-04T11:49:19Z

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

@dlangBugzillaToGithub
Copy link
Author

lt.infiltrator commented on 2015-12-02T17:18:01Z

I like it.  Have you put in a PR yet?

@dlangBugzillaToGithub
Copy link
Author

dlang-bugzilla (@CyberShadow) commented on 2017-07-07T16:43:58Z

(In reply to Andrej Mitrovic from comment #2)
> +            if (dg.funcptr != &Object.toString)

Pretty devious. I think it's not unreasonable.

@dlangBugzillaToGithub
Copy link
Author

andrej.mitrovich (@AndrejMitrovic) commented on 2022-07-04T17:09:03Z

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.

@LightBender LightBender removed the P4 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants