www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Tuples printing

reply "bearophile" <bearophileHUGS lycos.com> writes:
This is a topic I've already discussed a little in past.

In D I use tuples often, and I print them all the time, mostly 
while I write the code. Ranges of tuples are generated by some 
Phobos functions, and are generated by my map functios too. But 
if you print those ranges you quickly find a problem. A simple 
example program:


void main() {
     import std.stdio, std.typecons;

     alias RGB = Tuple!(ubyte,"R", ubyte,"G", ubyte,"B");
     const arr = [RGB(1, 2, 3), RGB(4, 5, 6), RGB(7, 8, 9)];

     writeln(arr);
}


It prints:

[const(Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(1, 2, 3), 
const(Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(4, 5, 6), 
const(Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(7, 8, 9)]


If your range of tuples grows larger, the printing becomes too 
much long and too much noisy. The signal gets almost lots.

A simple solution is to print tuples inside ranges as just 
(field1, field2, ...), and keep the same printing style if you 
print a single tuple:

writeln(RGB(1, 2, 3))
writeln(arr);
==>
Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(1, 2, 3)
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]

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

There are sufficiently common situations where you want a more 
precise textual representation of a tuple (and you can't override 
the Tuple.toString). See:
https://issues.dlang.org/show_bug.cgi?id=12106

The idea comes from the syntax to format the key and values of an 
associative array, that is currently available:

import std.stdio: writefln;
void main() {
     auto aa = [1: 10, 2: 20, 3: 30];
     writefln("%(%d: %d\n%)", aa);
}


Its output:

1: 10
2: 20
3: 30


So I've suggested a similar syntax for a range of tuples:


import std.stdio: writefln;
import std.range: zip;
void main() {
     auto r1 = zip([1, 2, 3], [10, 20, 30]);
     writefln("%(%d: %d\n%)", r1);
     auto r2 = zip([1, 2, 3], [10, 20, 30], [100, 200, 300]);
     writefln("%(%d: %d, %d\n%)", r2);
}



If you use only one formatting % then it formats the whole tuple, 
otherwise it requires exactly as many % as the fields of the 
tuple. But this syntax is ambiguous when you have a range of 
1-tuples:


import std.stdio: writefln;
import std.range: zip;
void main() {
     auto r0 = zip([10, 20, 30]);
     writefln("%(%s\n%)", r0);
}


Currently this works and outputs:

Tuple!int(10)
Tuple!int(20)
Tuple!int(30)

Do you have suggestions?

Thank you, bye,
bearophile
Jul 03 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Thu, Jul 03, 2014 at 09:52:35AM +0000, bearophile via Digitalmars-d wrote:
[...]
 void main() {
     import std.stdio, std.typecons;
 
     alias RGB = Tuple!(ubyte,"R", ubyte,"G", ubyte,"B");
     const arr = [RGB(1, 2, 3), RGB(4, 5, 6), RGB(7, 8, 9)];
 
     writeln(arr);
 }
 
 
 It prints:
 
 [const(Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(1, 2, 3),
 const(Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(4, 5, 6),
 const(Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(7, 8, 9)]
 
 
 If your range of tuples grows larger, the printing becomes too much
 long and too much noisy. The signal gets almost lots.
 
 A simple solution is to print tuples inside ranges as just (field1,
 field2, ...), and keep the same printing style if you print a single
 tuple:
 
 writeln(RGB(1, 2, 3))
 writeln(arr);
 ==>
 Tuple!(ubyte, "R", ubyte, "G", ubyte, "B"))(1, 2, 3)
 [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
[...] I like this idea. Looking at the code, it seems that Tuple.toString was specifically written to output tuples in the current format, though admittedly it's rather verbose. We *could* probably overload/rewrite it so that it permits %(...%) format specifiers, upon which the user could specify a different format, like the ones you suggested. (This could constitute a legitimate (rather than toy) use case for custom format specifiers, that I've written about. :-P) T -- MACINTOSH: Most Applications Crash, If Not, The Operating System Hangs
Jul 03 2014
parent "FrankLike" <1150015857 qq.com> writes:
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
Good idea.
And shoud easy to be used by foreach.

Frank
Jul 05 2014