On 01/22/2017 01:54 PM, Jon Degenhardt wrote:
I've been increasingly using output ranges in my code (the "component
programming" model described in several articles on the D site). It
works very well, except that it would often be more convenient to use
writeln style functions rather than 'put'. Especially when you start by
drafting a sketch of code using writeln functions, then convert it an
output range.

Seems an obvious thing, I'm wondering if I missed something. Are there
ways to use writeln style functions with output ranges?

--Jon

I don't think I understand the question. :)

If you need a variadic put(), then I've come up with the following mildly tested AllAppender. Just as a reminder, I've also used std.range.tee that allows tapping into the stream to see what's flying through:

import std.array : Appender, appender;
import std.stdio : writeln;

struct AllAppender(T) {
    Appender!T app;
    alias app this;

    void put(Args...)(Args args) {
        foreach (arg; args) {
            static if (__traits(compiles, app.put(arg))) {
                app.put(arg);
            }
            else {
                import std.conv : to;
                app.put(arg.to!T);
            }
        }
    }
}

import std.range : isOutputRange;
static assert(isOutputRange!(AllAppender!string, int));
static assert(isOutputRange!(AllAppender!string, double));

auto allAppender(T)() {
    return AllAppender!T();
}

void main() {
    auto a = allAppender!string();
    a.put(1, "hello");

    import std.range : tee;
    import std.algorithm : copy;
    [ 10, 20, 30 ]
        .tee!(e => writeln("appending ", e))
        .copy(a);

    writeln(a.data);
}

Ali

Reply via email to