digitalmars.D - Printing tuples
- bearophile (38/41) Sep 06 2011 Textual printing in D (and other languages) has some needs like:
- Timon Gehr (4/45) Sep 06 2011 Note that
- travert phare.normalesup.org (Christophe) (10/10) Sep 06 2011 writeln never writes the name of the printed variable, except for a
- bearophile (13/16) Sep 06 2011 Years after my first request, now given this program:
- Andrei Alexandrescu (10/20) Sep 06 2011 Yah, the problem with making array elements printed the same as
- Alix Pexton (7/10) Sep 06 2011 If JSON stands for JavaScript Object Notation[1], then the D equivalent
Textual printing in D (and other languages) has some needs like: 1) It needs to be readable, because first of all is meant to be read by people. 2) Where possible it needs to be as unambiguous as possible, because when you have several writeln you want all the help to know what part of the text is produced by one specific writeln. Often it's useful to receive some information about the type of the printed data, because in D you are allowed to write: void foo(T)(T x) { writeln(x); } In such cases it's useful to have some hint of the type of x in the textual output itself. 3) It's often handy to have a textual output that is parsable to reproduce the printed data structure (it's a kind of serialization). But such needs sometimes go against each other. Serialization asks for a fully unambiguous texual representation, but this sometimes produces a long or hard to read textual output. In such cases you have to choose what purpose is more important, or what's more important between consistency and practicality. I think that readability usually wins here because the main purpose of writeln() is not serialization. Serializability ("unprinting") is a secondary purpose of writeln(). Both common proverbs and the Python Zen often say opposite things because reality is complex, and hard strictly consistent rules in practice are often suboptimal:Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity.To show my point here is a small program, it generates just fifteen small tuples and prints them. I print tuples often in my code, so I am interested in this: import std.stdio, std.typecons; void main () { alias Tuple!(double,"posx", double,"posy", size_t,"count") T; T[] a; foreach (i; 0 .. 15) a ~= T(i*1.5, i*2.2, i); writeln(a[0]); writeln(a); } With the latest Phobos beta it prints: Tuple!(double,"posx",double,"posy",uint,"count")(0, 0, 0) [Tuple!(double,"posx",double,"posy",uint,"count")(0, 0, 0), Tuple!(double,"posx",double,"posy",uint,"count")(1.5, 2.2, 1), Tuple!(double,"posx",double,"posy",uint,"count")(3, 4.4, 2), Tuple!(double,"posx",double,"posy",uint,"count")(4.5, 6.6, 3), Tuple!(double,"posx",double,"posy",uint,"count")(6, 8.8, 4), Tuple!(double,"posx",double,"posy",uint,"count")(7.5, 11, 5), Tuple!(double,"posx",double,"posy",uint,"count")(9, 13.2, 6), Tuple!(double,"posx",double,"posy",uint,"count")(10.5, 15.4, 7), Tuple!(double,"posx",double,"posy",uint,"count")(12, 17.6, 8), Tuple!(double,"posx",double,"posy",uint,"count")(13.5, 19.8, 9), Tuple!(double,"posx",double,"posy",uint,"count")(15, 22, 10), Tuple!(double,"posx",double,"posy",uint,"count")(16.5, 24.2, 11), Tuple!(double,"posx",double,"posy",uint,"count")(18, 26.4, 12), Tuple!(double,"posx",double,"posy",uint,"count")(19.5, 28.6, 13), Tuple!(double,"posx",double,"posy",uint,"count")(21, 30.8, 14)] This textual output is good because it's a fully precise textual representation of the printed data structure, but in my opinion this is too much long and noisy. The information is almost drowning in noise. So: 1) I like that textual representation of single tuples (like the one printed by writeln(a[0]); ); 2) But I'd like a shorter textual representation of tuples when they are inside a collection. So I'd like this textual output for that program: Tuple!(double,"posx",double,"posy",uint,"count")(0, 0, 0) [tuple(0.0, 0.0, 0), tuple(1.5, 2.2, 1), tuple(3.0, 4.4, 2), tuple(4.5, 6.6, 3), tuple(6.0, 8.8, 4), tuple(7.5, 11.0, 5), tuple(9.0, 13.2, 6), tuple(10.5, 15.4, 7), tuple(12.0, 17.6, 8), tuple(13.5, 19.8, 9), tuple(15.0, 22.0, 10), tuple(16.5, 24.2, 11), tuple(18.0, 26.4, 12), tuple(19.5, 28.6, 13), tuple(21.0, 30.8, 14)] Notes: - This textual representation can be deserialized just like the precedent one, but it's more readable. - This textual representation is not exactly the same, because the field named are lost in the array. - Floating point values have a ".0" added where they don't have decimal digits, this allows all those tuples to be of the same type (double,double,int). This discussion comes from this bug report: http://d.puremagic.com/issues/show_bug.cgi?id=3813 Bye, bearophile
Sep 06 2011
On 09/06/2011 11:30 AM, bearophile wrote:Textual printing in D (and other languages) has some needs like: 1) It needs to be readable, because first of all is meant to be read by people. 2) Where possible it needs to be as unambiguous as possible, because when you have several writeln you want all the help to know what part of the text is produced by one specific writeln. Often it's useful to receive some information about the type of the printed data, because in D you are allowed to write: void foo(T)(T x) { writeln(x); } In such cases it's useful to have some hint of the type of x in the textual output itself. 3) It's often handy to have a textual output that is parsable to reproduce the printed data structure (it's a kind of serialization). But such needs sometimes go against each other. Serialization asks for a fully unambiguous texual representation, but this sometimes produces a long or hard to read textual output. In such cases you have to choose what purpose is more important, or what's more important between consistency and practicality. I think that readability usually wins here because the main purpose of writeln() is not serialization. Serializability ("unprinting") is a secondary purpose of writeln(). Both common proverbs and the Python Zen often say opposite things because reality is complex, and hard strictly consistent rules in practice are often suboptimal:Note that TypeTuple!(1,2,3).stringof == "tuple(1,2,3)" Which is bad imho.Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity.To show my point here is a small program, it generates just fifteen small tuples and prints them. I print tuples often in my code, so I am interested in this: import std.stdio, std.typecons; void main () { alias Tuple!(double,"posx", double,"posy", size_t,"count") T; T[] a; foreach (i; 0 .. 15) a ~= T(i*1.5, i*2.2, i); writeln(a[0]); writeln(a); } With the latest Phobos beta it prints: Tuple!(double,"posx",double,"posy",uint,"count")(0, 0, 0) [Tuple!(double,"posx",double,"posy",uint,"count")(0, 0, 0), Tuple!(double,"posx",double,"posy",uint,"count")(1.5, 2.2, 1), Tuple!(double,"posx",double,"posy",uint,"count")(3, 4.4, 2), Tuple!(double,"posx",double,"posy",uint,"count")(4.5, 6.6, 3), Tuple!(double,"posx",double,"posy",uint,"count")(6, 8.8, 4), Tuple!(double,"posx",double,"posy",uint,"count")(7.5, 11, 5), Tuple!(double,"posx",double,"posy",uint,"count")(9, 13.2, 6), Tuple!(double,"posx",double,"posy",uint,"count")(10.5, 15.4, 7), Tuple!(double,"posx",double,"posy",uint,"count")(12, 17.6, 8), Tuple!(double,"posx",double,"posy",uint,"count")(13.5, 19.8, 9), Tuple!(double,"posx",double,"posy",uint,"count")(15, 22, 10), Tuple!(double,"posx",double,"posy",uint,"count")(16.5, 24.2, 11), Tuple!(double,"posx",double,"posy",uint,"count")(18, 26.4, 12), Tuple!(double,"posx",double,"posy",uint,"count")(19.5, 28.6, 13), Tuple!(double,"posx",double,"posy",uint,"count")(21, 30.8, 14)] This textual output is good because it's a fully precise textual representation of the printed data structure, but in my opinion this is too much long and noisy. The information is almost drowning in noise. So: 1) I like that textual representation of single tuples (like the one printed by writeln(a[0]); ); 2) But I'd like a shorter textual representation of tuples when they are inside a collection. So I'd like this textual output for that program: Tuple!(double,"posx",double,"posy",uint,"count")(0, 0, 0) [tuple(0.0, 0.0, 0), tuple(1.5, 2.2, 1), tuple(3.0, 4.4, 2), tuple(4.5, 6.6, 3), tuple(6.0, 8.8, 4), tuple(7.5, 11.0, 5), tuple(9.0, 13.2, 6), tuple(10.5, 15.4, 7), tuple(12.0, 17.6, 8), tuple(13.5, 19.8, 9), tuple(15.0, 22.0, 10), tuple(16.5, 24.2, 11), tuple(18.0, 26.4, 12), tuple(19.5, 28.6, 13), tuple(21.0, 30.8, 14)] Notes: - This textual representation can be deserialized just like the precedent one, but it's more readable. - This textual representation is not exactly the same, because the field named are lost in the array. - Floating point values have a ".0" added where they don't have decimal digits, this allows all those tuples to be of the same type (double,double,int). This discussion comes from this bug report: http://d.puremagic.com/issues/show_bug.cgi?id=3813 Bye, bearophile
Sep 06 2011
writeln never writes the name of the printed variable, except for a tuple (or some custom types,obviously). Moreover, the output of writeln(T) and writeln(T[]) should be consistent. The output should look somthing like: "(1.5, 1, my string)". And if you want to know the name of the tuple before your tuple, you should write: writeln(typeof(t).stringof, t) Do you agree ? -- Christophe
Sep 06 2011
Christophe:Moreover, the output of writeln(T) and writeln(T[]) should be consistent.Years after my first request, now given this program: import std.stdio; void main() { writeln("foo"); writeln(["foo"]); } D prints (this problem is what has pushed me to add bug reports to Bugzilla in the first place, so it was one of my pet peeves): foo ["foo"]The output should look somthing like: "(1.5, 1, my string)".This is very clean, but this is different from the look of D tuple literals. Bye, bearophile
Sep 06 2011
On 9/6/11 12:32 PM, bearophile wrote:Christophe:Yah, the problem with making array elements printed the same as individual items is ambiguity. Inside an array the reader (human or not) must unambiguously identify elements from separators, otherwise printing square brackets and commas results in confusion. This reminds me, we should have a function e.g. std.conv.escape() that given the string "foo\nbar" returns the string "\"foo\\nbar\"". I mean sometimes we want to print "DSON"-formatted stuff without it being in an array. AndreiMoreover, the output of writeln(T) and writeln(T[]) should be consistent.Years after my first request, now given this program: import std.stdio; void main() { writeln("foo"); writeln(["foo"]); } D prints (this problem is what has pushed me to add bug reports to Bugzilla in the first place, so it was one of my pet peeves):
Sep 06 2011
On 06/09/2011 19:24, Andrei Alexandrescu wrote:sometimes we want to print "DSON"-formatted stuff without it being in an array. AndreiIf JSON stands for JavaScript Object Notation[1], then the D equivalent would surely be DON? I'm sure no prominent members of the community will mind and there would be absolutely no confusion ^^ A... [1] see json.org, although I acknowledge that some people prefer to insert "Serialized".
Sep 06 2011