digitalmars.D - Tuples printing
- bearophile (68/68) Jul 03 2014 This is a topic I've already discussed a little in past.
- H. S. Teoh via Digitalmars-d (14/43) Jul 03 2014 [...]
- FrankLike (4/4) Jul 05 2014 [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
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
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
[(1, 2, 3), (4, 5, 6), (7, 8, 9)] Good idea. And shoud easy to be used by foreach. Frank
Jul 05 2014