[Issue 9882] New: Add UFCS-friendly printing functions

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Apr 5 05:27:10 PDT 2013


http://d.puremagic.com/issues/show_bug.cgi?id=9882

           Summary: Add UFCS-friendly printing functions
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody at puremagic.com
        ReportedBy: bearophile_hugs at eml.cc


--- Comment #0 from bearophile_hugs at eml.cc 2013-04-05 05:27:08 PDT ---
This program prints the transposed of some strings. You can see that if you
want to print the result of a long UFCS chain with a formatting string you are
forced to break the chain, and it's not immediate to print intermediate steps:


import std.stdio: writeln, writefln;
import std.range: iota, transversal;
import std.algorithm: map, reduce, max;

void main() {
    immutable txt = ["Line one", "Line 2"];

    writefln("%(%s\n%)", txt
                         .map!q{ a.length }
                         .map!((s){ writeln(s); return s; })
                         .reduce!max
                         .iota
                         .map!(i => txt.transversal(i)));
}



Output:

8
6
LL
ii
nn
ee

o2
n
e

- - - - - - - - - - - - - - - - - - - - - - -

A simple way to solve both problems is to add to std.stdio four printing
functions that are UFCS-friendly, where the format string is leading:


import std.stdio: write, writeln, writef, writefln;
import std.traits: isSomeString;

auto uWrite(T)(T data) {
    write(data);
    return data;
}

auto uWriteln(T)(T data) {
    writeln(data);
    return data;
}

auto uWritef(T, TS)(T data, TS format) if (isSomeString!TS) {
    writef(format, data);
    return data;
}

auto uWritefln(T, TS)(T data, TS format) if (isSomeString!TS) {
    writefln(format, data);
    return data;
}

// Usage demo -------------

import std.range: iota, transversal;
import std.algorithm: map, reduce, max;

void main() {
    immutable txt = ["Line one", "Line 2"];

    txt
    .map!q{ a.length }
    .uWriteln
    .reduce!max
    .iota
    .map!(i => txt.transversal(i))
    .uWritefln("%(%s\n%)");
}



Output (also note that 8 and 6 are printed with the array syntax):

[8, 6]
LL
ii
nn
ee

o2
n
e

- - - - - - - - - - - - - - - - - - - - - - -

Disadvantages:

1) A .tap() function that allows to perform some impure operation on the
stream, but keep it flowing, is more general than those printing functions.
Something like this:



import std.range: iota, transversal;
import std.algorithm: map, reduce, max;
import std.range: tap;

void main() {
    immutable txt = ["Line one", "Line 2"];

    txt
    .map!q{ a.length }
    .tap!q{ writeln(s) }
    .reduce!max
    .iota
    .map!(i => txt.transversal(i))
    .tap!q{ writefln("%(%s\n%)", s) };
}


In practice I've seen that in most cases I such tap only to print.



2) functions like that uWritefln() accept only the format string beside the
stream to print. So you can't print the stream plus some other data. In theory
this can be solved with printing functions like this:


auto uWrite(TArgs...)(TArgs items) {
    write(items);
    return items[0];
}

auto uWriteln(TArgs...)(TArgs items) {
    writeln(items);
    return items[0];
}

auto uWritef(TArgs...)(TArgs items) if (isSomeString!(TArgs[$ - 1])) {
    writef(items[$ - 1], items[0 .. $ - 1]);
    return items[0];
}

auto uWritefln(TArgs...)(TArgs items) if (isSomeString!(TArgs[$ - 1])) {
    writefln(items[$ - 1], items[0 .. $ - 1]);
    return items[0];
}


But their order of printing is not intuitive, so I suggest to not use them.


See also the discussion thread:
http://forum.dlang.org/thread/vkuzklqsqqoawkbpoxpg@forum.dlang.org

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list