Skip to content

Fix Issue 5945: redBlackTree printing #3572

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

Merged
merged 1 commit into from
Sep 3, 2015

Conversation

JackStouffer
Copy link
Member

Low hanging fruit:
https://issues.dlang.org/show_bug.cgi?id=5945

My solution is a little different than the original suggestion, as it isn't known if the redBlackTree factory function was used or not.

@schveiguy
Copy link
Member

I think this is not the correct solution, as it allocates a temporary string that is immediately garbage.

The correct solution, I think, is to print the range, as identified in the bug report. As there is no way for RedBlackTree to hook that, I think the work to be done is not in RedBlackTree, but in format/writefln.

@yebblies
Copy link
Member

Can't you just formattedWrite(sink, "%s", this[]) with the new toString?

@quickfur
Copy link
Member

It's better to use this overload of toString:

void toString(scope void delegate(const(char)[]) sink);

@schveiguy
Copy link
Member

Can't you just formattedWrite(sink, "%s", this[]) with the new toString?

I didn't know that could be done. Sounds like a good solution.

@JackStouffer
Copy link
Member Author

@yebblies You mean like this?

override string toString() {
    import std.format : formattedWrite;
    import std.array : appender;

    auto str = appender!string();
    formattedWrite(str, "RedBlackTree(%s)", this[]);
    return str.data;
}

@schveiguy
Copy link
Member

He means the toString variant that @quickfur alluded to. I'm not sure how it works on classes though.

@JackStouffer
Copy link
Member Author

@schveiguy But yebblies' comment was made before quickfur's comment.

@schveiguy
Copy link
Member

I know, both were referring to the new style of toString, which instead of creating a garbage strings, accepts a "sink" function to put all string output into.

@JackStouffer
Copy link
Member Author

I don't understand that overload. Isn't toString supposed to return a string? What does the sink variable refer to? Are there any examples of that being used anywhere?

@schveiguy
Copy link
Member

http://dlang.org/phobos/std_format.html#.formatValue

Scroll down until you see the overload that takes an aggregate with toString. It will explain how the overloads work.

Again, I'm not 100% sure how it works for classes, but I think it should work just by adding that overload (may have to provide a string returning overload too).

@JackStouffer
Copy link
Member Author

Ok, so I changed the method to:

void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const {
        sink("RedBlackTree(");
        sink.formatValue(this[], fmt);
        sink(")");
}

But now I am running into linker errors from std.format again, even though the unit tests pass. Original bug report: https://issues.dlang.org/show_bug.cgi?id=14959

But now the errors are

$ dmd/src/dmd test.d
Undefined symbols for architecture x86_64:
  "_D3std6format32__T14formatUnsignedTDFAxaZvTmTaZ14formatUnsignedFDFAxaZvmKxS3std6format18__T10FormatSpecTaZ10FormatSpeckbZv", referenced from:
      _D3std6format32__T14formatIntegralTDFAxaZvTlTaZ14formatIntegralFDFAxaZvxlKxS3std6format18__T10FormatSpecTaZ10FormatSpeckmZv in test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
--- errorlevel 1

Where test.d is

import std.stdio, std.container;
void main() {
    auto t = redBlackTree(0, 7, 5, 2);
    writeln(t);
}

@DmitryOlshansky
Copy link
Member

But now I am running into linker errors from std.format again, even though the unit tests pass. Original bug report: https://issues.dlang.org/show_bug.cgi?id=14959

Just add the unittest and we'll see what the auto-tester says

@JackStouffer
Copy link
Member Author

Well the problem is that the tests don't cover the toString method, so even if the tests pass it doesn't really say anything. Also, I now don't have a way to check if the toString method actually does what I want it to do.

@DmitryOlshansky
Copy link
Member

Also, I now don't have a way to check if the toString method actually does what I want it to do.

assert(somRbT.to!string == "[....]'); 

No?

@JackStouffer
Copy link
Member Author

At the time I was referring to the linker errors and my inability to compile the program. But after I re-downloaded dmd and druntime I was finally able to compile the test program in the issue.

Thank you for reminding me about this. I have added your unit test now.

@DmitryOlshansky
Copy link
Member

Otherwise LGTM

@JackStouffer
Copy link
Member Author

@DmitryOlshansky Added extra tests.

@@ -20,6 +20,7 @@ Authors: Steven Schveighoffer, $(WEB erdani.com, Andrei Alexandrescu)
module std.container.rbtree;

import std.functional : binaryFun;
import std.format;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... Move that to toString method itself? Since RB-Tree is a template that should cut down on number of imports if RB-Tree is not instantiated but std.container is imported.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately the void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const overload doesn't work if std.format is a local import.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could do something like:

template toString(DG)
{
    import std.format;
    void toString(scope DG sink, FormatSpec!char fmt) const
    {
        ...
    }
}

override string toString() const
{
    auto app = appender!string();
    toString(app, FormatSpec!char("%s"));
    return app.data;
}

edit:
Err, scratch the runtime polymorphic overload, clearly it would still require FormatSpec.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we have to make do with global import for now

@DmitryOlshansky
Copy link
Member

Leaving last word to @schveiguy

@schveiguy
Copy link
Member

Well, it's better than the current behavior, and adjusting the format later isn't going to make a huge difference.

@@ -1669,6 +1670,12 @@ assert(equal(rbt[], [5]));
}
}

void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be documented? I'm honestly not sure, because I don't know what the policy is for documenting toString functions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing a search through Phobos I see examples of both documentation and no documentation, so your call.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I say err on the side of documentation for public functions :)

@JackStouffer
Copy link
Member Author

Talk about damning with faint praise ;)

@JackStouffer
Copy link
Member Author

Added documentation.

Returns a user-friendly string representation by writing to the $(D sink).
For more info, see $(D std.format.formatValue).
*/
void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns void, so starting the doc with "Returns" is not correct.

I think this might be acceptable:

Formats the RedBlackTree into a sink function. For more info see $(D std.format.formatValue)

@schveiguy
Copy link
Member

Talk about damning with faint praise ;)

Heh, I will rephrase: I don't like the redundant brackets, but the output is not confusing or misleading, it just looks ugly to me :) Bikeshedding shouldn't derail this.

In any case, I appreciate the effort to fix the bug, and I think it's an acceptable solution.

@JackStouffer
Copy link
Member Author

Fixed documentation

@schveiguy
Copy link
Member

Auto-merge toggled on

@JackStouffer
Copy link
Member Author

Woohoo! My first real contribution to Phobos!

@DmitryOlshansky
Copy link
Member

Woohoo! My first real contribution to Phobos!

Congrats! ;)

schveiguy added a commit that referenced this pull request Sep 3, 2015
Fix Issue 5945: redBlackTree printing
@schveiguy schveiguy merged commit 1272c1a into dlang:master Sep 3, 2015
@JackStouffer JackStouffer deleted the issue5945 branch September 9, 2015 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants