www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why does toString() exist? It seems useless.

reply Don <nospam nospam.com.au> writes:
I cannot understand the rationale for a toString() member function which 
doesn't support formatting.

I don't think I've ever made a class which only has a single format 
option. If the class contains any integers, I want to specify whether it 
should use hex or decimal, leading zeros, sign. If it contains floating 
point numbers, it's number of digits, scientific notation, hex or 
decimal, and what to do with NaNs. And of course there are locales.

Seriously, I cannot remember ever not having this requirement, so I 
cannot imagine a use for toString().

C++ got around this by giving state to the iostream classes. As far as I 
can tell, neither Phobos nor Tango provide any support at all.

Practical example: BigInt (which I'm developing in both Tango and 
Phobos). It is a struct. How can it support I/O? I can't work out how to 
do it in either library.
Aug 18 2008
next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Don wrote:

 I cannot understand the rationale for a toString() member function which
 doesn't support formatting.
 
 I don't think I've ever made a class which only has a single format
 option. If the class contains any integers, I want to specify whether it
 should use hex or decimal, leading zeros, sign. If it contains floating
 point numbers, it's number of digits, scientific notation, hex or
 decimal, and what to do with NaNs. And of course there are locales.
 
 Seriously, I cannot remember ever not having this requirement, so I
 cannot imagine a use for toString().
 
 C++ got around this by giving state to the iostream classes. As far as I
 can tell, neither Phobos nor Tango provide any support at all.
 
 Practical example: BigInt (which I'm developing in both Tango and
 Phobos). It is a struct. How can it support I/O? I can't work out how to
 do it in either library.

It is not useless, but it would indeed be useful to be able to pass a format string to it - toString(char[] fmt) - or similar. Note that if structs could have interfaces, then this wouldn't really be a problem. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Aug 18 2008
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Don Wrote:
 I cannot understand the rationale for a toString() member function which 
 doesn't support formatting.

I think the rationale is that it's a simple function that performs a simple thing with an easy to use and easy to learn syntax, I have found it useful often. For more complex purposes you can write your own printing methods, or you can write a method that changes the printing state of the class/struct, that is later read and used when you call toString() and used to change its behavior. So I have created a graph class that by default when you call toString() gives a compact and simple textual representation of the graph. Then there are other methods, one that returns a string that shows the matrix of links, another that shows the weights of the arcs too, etc. There is also the possibility to modify the printing defaults with another method, to then later toString() acts differently. Bye, bearophile
Aug 18 2008
parent reply Don <nospam nospam.com.au> writes:
bearophile wrote:
 Don Wrote:
 I cannot understand the rationale for a toString() member function which 
 doesn't support formatting.

I think the rationale is that it's a simple function that performs a simple thing with an easy to use and easy to learn syntax, I have found it useful often.

I think it encourages a very bad programming style. It makes ONE case very easy, but does nothing for the other cases. It doesn't scale at all.
 For more complex purposes you can write your own printing methods, 

 or you can write a method that changes the printing state of the class/struct, 
 that is later read and used when you call toString() and used to 

But the way it is formatted should be a property of the output stream, I think, not a property of the object. Certainly this is the way C and C++ I/O works.
 
 So I have created a graph class that by default when you call toString() gives
a compact and simple textual representation of the graph. 

matrix of links, another that shows the weights of the arcs too, etc. There is also the possibility to modify the printing defaults with another method, to then later toString() acts differently. Then I got suspicious that this might have come from Java or .NET. I googled for toString in Java and found: --- http://www.javapractices.com/topic/TopicAction.do?Id=55 --- "The toString method is widely implemented. It provides a simple, convenient mechanism for debugging classes during development. It is also widely used for logging, and for passing informative error messages to Exception constructors and assertions. When used in these informal ways, the exact format of toString is not part of the contract of the method, and callers should not rely on the exact format of the returned String." --- Now this makes sense. It's a useful hack. If it's just for debugging and error messages, that's fine. But if that is what it's for, the normal runtime I/O should discourage its use elsewhere (eg, by appending the class name in front). OTOH if it is intended for general I/O, I think it's a horribly broken design.
Aug 18 2008
next sibling parent Frank Benoit <keinfarbton googlemail.com> writes:
Don schrieb:
 OTOH if it is intended for general I/O, I think it's a horribly broken 
 design.

What do you think about doing one of 1.) change signature in object.Object to char[] toString( char[] fmt = null) to give the object the possibility to use the format information. Well, would break all code :/ 2.) Create a standard interface for doing that interface Formatable { char[] toString( char[] fmt ); } The object can implement this interface, the user can try to cast to this interface. if( auto formatable = cast(Formatable)obj ){ print( formatable.toString(fmt)); } else if( obj !is null ){ print( obj.toString()); } else{ print( "null" ); }
Aug 18 2008
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Don:
 But the way it is formatted should be a property of the output stream, I 
 think, not a property of the object. Certainly this is the way C and C++ 
 I/O works.

You may be right, I am learning still a lot about such matters. But how can the output stream know about the many ways to print a graph? (I don't know enough about C++ streams). Bye, bearophile
Aug 18 2008
prev sibling parent Max Samukha <samukha voliacable.com.removethis> writes:
On Mon, 18 Aug 2008 15:15:51 +0200, Don <nospam nospam.com.au> wrote:

bearophile wrote:
 Don Wrote:
 I cannot understand the rationale for a toString() member function which 
 doesn't support formatting.

I think the rationale is that it's a simple function that performs a simple thing with an easy to use and easy to learn syntax, I have found it useful often.

I think it encourages a very bad programming style. It makes ONE case very easy, but does nothing for the other cases. It doesn't scale at all.
 For more complex purposes you can write your own printing methods, 

 or you can write a method that changes the printing state of the class/struct, 
 that is later read and used when you call toString() and used to 

But the way it is formatted should be a property of the output stream, I think, not a property of the object. Certainly this is the way C and C++ I/O works.
 
 So I have created a graph class that by default when you call toString() gives
a compact and simple textual representation of the graph. 

matrix of links, another that shows the weights of the arcs too, etc. There is also the possibility to modify the printing defaults with another method, to then later toString() acts differently. Then I got suspicious that this might have come from Java or .NET.

FWIW, .NET provides IFormattable interface that allows objects to imlement custom formatting: interface IFormattable { string toString(string fmt, IFormatProvider fProvider); } class C : IFormattable { string toString(string fmt, IFormatProvider fProvider) { if (fProvider !is null) { // try to get a formater for this type // from fProvider } else { switch (fmt) { // do formatting based on the format string } } } }
I googled for toString in Java and found:
---
http://www.javapractices.com/topic/TopicAction.do?Id=55
---
"The toString method is widely implemented. It provides a simple, 
convenient mechanism for debugging classes during development. It is 
also widely used for logging, and for passing informative error messages 
to Exception constructors and assertions. When used in these informal 
ways, the exact format of toString is not part of the contract of the 
method, and callers should not rely on the exact format of the returned 
String."
---
Now this makes sense. It's a useful hack. If it's just for debugging and 
error messages, that's fine. But if that is what it's for, the normal 
runtime I/O should discourage its use elsewhere (eg, by appending the 
class name in front).

OTOH if it is intended for general I/O, I think it's a horribly broken 
design.

Aug 20 2008
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Don" wrote
I cannot understand the rationale for a toString() member function which 
doesn't support formatting.

 I don't think I've ever made a class which only has a single format 
 option. If the class contains any integers, I want to specify whether it 
 should use hex or decimal, leading zeros, sign. If it contains floating 
 point numbers, it's number of digits, scientific notation, hex or decimal, 
 and what to do with NaNs. And of course there are locales.

 Seriously, I cannot remember ever not having this requirement, so I cannot 
 imagine a use for toString().

 C++ got around this by giving state to the iostream classes. As far as I 
 can tell, neither Phobos nor Tango provide any support at all.

 Practical example: BigInt (which I'm developing in both Tango and Phobos). 
 It is a struct. How can it support I/O? I can't work out how to do it in 
 either library.

As you have discovered, it is for simple debugging. However, it's not even close to as useful as Java, where if you combine a string with an object, it automatically calls the toString function. As far as supporting an output method, I think toString is completely the wrong way to look at it. A simple example is a container class, such as a vector of ints. Let's say you are outputting a vector of ints every time it has changed. What ends up happening is you build a (possibly huge) string every time you output the vector, and then are throwing the string away! When all you really need is about 20 bytes of stack space to create the individual int strings and then output to an i/o function. Even with a format string, that doesn't solve this problem. What I would like to see is an output method in Object that looks like: int output(int delegate(char[] x) sink, char[] fmt = null); And something like how 'toString' works in a struct (where there is an xoutput function in the struct typeinfo class). This is a generic solution, it would be customized to the appropriate i/o library of Tango or Phobos. Possibly the format strings would be different based on the I/O (i.e. Phobos uses printf style formatting constructs, Tango uses .NET style). -Steve
Aug 18 2008
parent Fawzi Mohamed <fmohamed mac.com> writes:
On 2008-08-18 16:28:36 +0200, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 "Don" wrote
 I cannot understand the rationale for a toString() member function which
 doesn't support formatting.
 [...]


yes
 However, it's not even close to as useful as Java, where if you combine a
 string with an object, it automatically calls the toString function.
 
 As far as supporting an output method, I think toString is completely the
 wrong way to look at it.  A simple example is a container class, such as a
 vector of ints.
 
 Let's say you are outputting a vector of ints every time it has changed.
 What ends up happening is you build a (possibly huge) string every time you
 output the vector, and then are throwing the string away!  When all you
 really need is about 20 bytes of stack space to create the individual int
 strings and then output to an i/o function.
 
 Even with a format string, that doesn't solve this problem.
 
 What I would like to see is an output method in Object that looks like:
 
 int output(int delegate(char[] x) sink, char[] fmt = null);

I fully agree I normally write a method that writes to a stream, with handles to tailor the output. I also often write a desc method that gives a detailed description of all the variables of the object. Then I write toString that calls one of these methods with some default arguments on a special stream the creates a string. In general stream based output is much superior to conversion to a string (more efficient and often simpler to write), and when needed one can use a special stream that returns a string. In tango I use a Print!(T) instance as nice to use stream, nicer than a sink delegate. I wrote a Stringify class that like Python StringIO returns the collected string upon request.
 And something like how 'toString' works in a struct (where there is an
 xoutput function in the struct typeinfo class).

yes would also be nice to have
 This is a generic solution, it would be customized to the appropriate i/o
 library of Tango or Phobos.  Possibly the format strings would be different
 based on the I/O (i.e. Phobos uses printf style formatting constructs, Tango
 uses .NET style).

I am not too sure that I want to always have a format string, encoding and decoding it might be tedious, normally having a method with extra arguments is better. Serialization is another topic, there the format should be defined by the stream. Fawzi
Aug 20 2008
prev sibling next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
Don wrote:
 I cannot understand the rationale for a toString() member function which 
 doesn't support formatting.

I agree. In Java, the toString() method *must* exist on the base Object class, because of constructs like this: String s = "hello" + (new World()); Without an implementation of toString(), it'd be impossible to support those kinds of automatic String conversion and concatenation (which actually do end up being pretty handy in logging & debugging statements). But since D doesn't support implicit String conversion, it seems pretty pointless. Incidentally, I'd be opposed to a toString(char[] format) method being a part of the Object class. I prefer the Tango (.NET style) formatting, and others surely prefer the printf style formatting in Phobos. If formatting strings became a part of the basic Object definition, I can imagine a lot of very annoyed developers, depending on which formatting style was chosen for Object. --benji
Aug 18 2008
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Benji Smith wrote:
 Don wrote:
 I cannot understand the rationale for a toString() member function 
 which doesn't support formatting.

I agree. In Java, the toString() method *must* exist on the base Object class, because of constructs like this: String s = "hello" + (new World()); Without an implementation of toString(), it'd be impossible to support those kinds of automatic String conversion and concatenation (which actually do end up being pretty handy in logging & debugging statements). But since D doesn't support implicit String conversion, it seems pretty pointless.

I think both Tango and phobos allow objects to be converted to strings when specified as parameters to a formatting function -- i.e. Stdout.format("{0}", obj) will call obj.toString().
Aug 19 2008
parent reply Don <nospam nospam.com.au> writes:
Robert Fraser wrote:
 Benji Smith wrote:
 Don wrote:
 I cannot understand the rationale for a toString() member function 
 which doesn't support formatting.

I agree. In Java, the toString() method *must* exist on the base Object class, because of constructs like this: String s = "hello" + (new World()); Without an implementation of toString(), it'd be impossible to support those kinds of automatic String conversion and concatenation (which actually do end up being pretty handy in logging & debugging statements). But since D doesn't support implicit String conversion, it seems pretty pointless.

I think both Tango and phobos allow objects to be converted to strings when specified as parameters to a formatting function -- i.e. Stdout.format("{0}", obj) will call obj.toString().

And that's the problem -- it's a really poor design, totally unsuitable for that purpose. Simple challenge: class Foo { public: double x; } 1. You want it to output x in the default way for the current locale. (eg, 5,35 or 5.35 depending on which country you're in). Write toString(). 2. Now write toString() such that: double y = 3.156892123; Foo z = new Foo; z.x = 3.156892123; writefln("%.3f, %.3f", y, z); writefln("%.4f, %.4f", y, z); (or Tango equivalent) produces the same results for y and z. Both of these should be trivial.
Aug 20 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
Don wrote:
 Robert Fraser wrote:
 Benji Smith wrote:
 Don wrote:
 I cannot understand the rationale for a toString() member function 
 which doesn't support formatting.

I agree. In Java, the toString() method *must* exist on the base Object class, because of constructs like this: String s = "hello" + (new World()); Without an implementation of toString(), it'd be impossible to support those kinds of automatic String conversion and concatenation (which actually do end up being pretty handy in logging & debugging statements). But since D doesn't support implicit String conversion, it seems pretty pointless.

I think both Tango and phobos allow objects to be converted to strings when specified as parameters to a formatting function -- i.e. Stdout.format("{0}", obj) will call obj.toString().

And that's the problem -- it's a really poor design, totally unsuitable for that purpose. Simple challenge: class Foo { public: double x; } 1. You want it to output x in the default way for the current locale. (eg, 5,35 or 5.35 depending on which country you're in). Write toString(). 2. Now write toString() such that: double y = 3.156892123; Foo z = new Foo; z.x = 3.156892123; writefln("%.3f, %.3f", y, z); writefln("%.4f, %.4f", y, z); (or Tango equivalent) produces the same results for y and z. Both of these should be trivial.

We had actually asked for some compiler changes to support this sort of formatting (necessary since the function signature for toString is hardcoded in the compiler for structs), but the request was denied, presumably as unnecessary. I don't remember the details of the request however--Lars would have to provide that. Sean
Aug 20 2008
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Sean Kelly wrote:

 Don wrote:
 Robert Fraser wrote:
 Benji Smith wrote:
 Don wrote:
 I cannot understand the rationale for a toString() member function
 which doesn't support formatting.

I agree. In Java, the toString() method *must* exist on the base Object class, because of constructs like this: String s = "hello" + (new World()); Without an implementation of toString(), it'd be impossible to support those kinds of automatic String conversion and concatenation (which actually do end up being pretty handy in logging & debugging statements). But since D doesn't support implicit String conversion, it seems pretty pointless.

I think both Tango and phobos allow objects to be converted to strings when specified as parameters to a formatting function -- i.e. Stdout.format("{0}", obj) will call obj.toString().

And that's the problem -- it's a really poor design, totally unsuitable for that purpose. Simple challenge: class Foo { public: double x; } 1. You want it to output x in the default way for the current locale. (eg, 5,35 or 5.35 depending on which country you're in). Write toString(). 2. Now write toString() such that: double y = 3.156892123; Foo z = new Foo; z.x = 3.156892123; writefln("%.3f, %.3f", y, z); writefln("%.4f, %.4f", y, z); (or Tango equivalent) produces the same results for y and z. Both of these should be trivial.

We had actually asked for some compiler changes to support this sort of formatting (necessary since the function signature for toString is hardcoded in the compiler for structs), but the request was denied, presumably as unnecessary. I don't remember the details of the request however--Lars would have to provide that.

It was more of a suggestion that something accommodating this should exist, with toString(char[] fmt) as an initial suggestion. I think it just slipped away as it wasn't a good enough solution, not really denied. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Aug 20 2008
parent Sean Kelly <sean invisibleduck.org> writes:
Lars Ivar Igesund wrote:
 Sean Kelly wrote:
 
 Don wrote:
 Robert Fraser wrote:
 Benji Smith wrote:
 Don wrote:
 I cannot understand the rationale for a toString() member function
 which doesn't support formatting.

In Java, the toString() method *must* exist on the base Object class, because of constructs like this: String s = "hello" + (new World()); Without an implementation of toString(), it'd be impossible to support those kinds of automatic String conversion and concatenation (which actually do end up being pretty handy in logging & debugging statements). But since D doesn't support implicit String conversion, it seems pretty pointless.

when specified as parameters to a formatting function -- i.e. Stdout.format("{0}", obj) will call obj.toString().

for that purpose. Simple challenge: class Foo { public: double x; } 1. You want it to output x in the default way for the current locale. (eg, 5,35 or 5.35 depending on which country you're in). Write toString(). 2. Now write toString() such that: double y = 3.156892123; Foo z = new Foo; z.x = 3.156892123; writefln("%.3f, %.3f", y, z); writefln("%.4f, %.4f", y, z); (or Tango equivalent) produces the same results for y and z. Both of these should be trivial.

formatting (necessary since the function signature for toString is hardcoded in the compiler for structs), but the request was denied, presumably as unnecessary. I don't remember the details of the request however--Lars would have to provide that.

It was more of a suggestion that something accommodating this should exist, with toString(char[] fmt) as an initial suggestion. I think it just slipped away as it wasn't a good enough solution, not really denied.

Oops, I stand corrected. Sean
Aug 21 2008
prev sibling next sibling parent BCS <ao pathlink.com> writes:
Reply to don,

 I cannot understand the rationale for a toString() member function
 which doesn't support formatting.
 
 I don't think I've ever made a class which only has a single format
 option. If the class contains any integers, I want to specify whether
 it should use hex or decimal, leading zeros, sign. If it contains
 floating point numbers, it's number of digits, scientific notation,
 hex or decimal, and what to do with NaNs. And of course there are
 locales.
 
 Seriously, I cannot remember ever not having this requirement, so I
 cannot imagine a use for toString().
 
 C++ got around this by giving state to the iostream classes. As far as
 I can tell, neither Phobos nor Tango provide any support at all.
 
 Practical example: BigInt (which I'm developing in both Tango and
 Phobos). It is a struct. How can it support I/O? I can't work out how
 to do it in either library.
 

I think the point is to have a least common denominator "Just give me *something*" method for debugging and the like. Anything more demanding is to complicated for the base class as it will never be flexible enough.
Aug 18 2008
prev sibling next sibling parent Christopher Wright <dhasenan gmail.com> writes:
Don wrote:
 I cannot understand the rationale for a toString() member function which 
 doesn't support formatting.

Nothing similar exists in Tango because, for structs, it requires compiler support. In Tango, you can specify formatting for a particular type by subclassing Layout and overriding munge. Or rather, you could, except munge is private. Relevant ticket: http://dsource.org/projects/tango/ticket/1247 On the other hand, I've only ever used toString for debug output, using external formatters for anything with user-visible results. Again, if Layout.munge were not private, you could add external formatters easily. This helps you not at all when using Phobos.
Aug 18 2008
prev sibling next sibling parent JAnderson <ask me.com> writes:
Don wrote:
 I cannot understand the rationale for a toString() member function which 
 doesn't support formatting.
 
 I don't think I've ever made a class which only has a single format 
 option. If the class contains any integers, I want to specify whether it 
 should use hex or decimal, leading zeros, sign. If it contains floating 
 point numbers, it's number of digits, scientific notation, hex or 
 decimal, and what to do with NaNs. And of course there are locales.
 
 Seriously, I cannot remember ever not having this requirement, so I 
 cannot imagine a use for toString().
 
 C++ got around this by giving state to the iostream classes. As far as I 
 can tell, neither Phobos nor Tango provide any support at all.
 
 Practical example: BigInt (which I'm developing in both Tango and 
 Phobos). It is a struct. How can it support I/O? I can't work out how to 
 do it in either library.

I think you can do much the same as iostream and still take advantage of toString. Something like: string foo = a.toString() ~ format(a, "..."); Where format would be special overloaded template (with specialization) that does conversions. -Joel
Aug 20 2008
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function which
doesn't 
 support formatting.

I think is useful only for debugging purposes.
 C++ got around this by giving state to the iostream classes.

I think C++ formatting is heavily ill. All the manipulator stuff is madness. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- No existiría el sonido del mar si faltara en la vida oreja y caracol. -- Ricardo Vaporeso. Cosquín, 1908.
Aug 22 2008
next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Leandro Lucarella wrote:
 Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function which
doesn't 
 support formatting.

I think is useful only for debugging purposes.
 C++ got around this by giving state to the iostream classes.

I think C++ formatting is heavily ill. All the manipulator stuff is madness.

It's horrific but surprisingly flexible. I've created stateful formatters for various protocols and made it work all invisibly with the formatting hooks provided in C++. For example: std::cout << a << b << c << std::flush; The above may perform lazy output of structured XML, some binary encoding, etc. It might be possible to get close with toString, but because it returns an array rather than writing into a buffer some of the flexibiliy (like lazy encoding) would definitely be lost. My experience with Java suggests that toString is meant for debugging purposes anyway. It's rare that an object will produce meaningful user-level output with its toString method. Sean
Aug 22 2008
parent reply Leandro Lucarella <llucax gmail.com> writes:
Sean Kelly, el 22 de agosto a las 12:46 me escribiste:
 Leandro Lucarella wrote:
Don, el 18 de agosto a las 12:41 me escribiste:
I cannot understand the rationale for a toString() member function which 
doesn't support formatting.

C++ got around this by giving state to the iostream classes.

madness.

It's horrific but surprisingly flexible. I've created stateful formatters for various protocols and made it work all invisibly with the formatting hooks provided in C++. For example: std::cout << a << b << c << std::flush; The above may perform lazy output of structured XML, some binary encoding, etc. It might be possible to get close with toString, but because it returns an array rather than writing into a buffer some of the flexibiliy (like lazy encoding) would definitely be lost. My experience with Java suggests that toString is meant for debugging purposes anyway. It's rare that an object will produce meaningful user-level output with its toString method.

I agree, I meant that D should do better. Like templates are for gurus in C++ and for people in D, formatting should be for people too in D (as opposed to C++ manipulators =). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- He cometido pecados, he hecho el mal, he sido víctima de la envidia, el egoísmo, la ambición, la mentira y la frivolidad, pero siempre he sido un padre argentino que quiere que su hijo triunfe en la vida. -- Ricardo Vaporeso
Aug 22 2008
next sibling parent reply Fawzi Mohamed <fmohamed mac.com> writes:
On 2008-08-22 22:10:21 +0200, Leandro Lucarella <llucax gmail.com> said:

 Sean Kelly, el 22 de agosto a las 12:46 me escribiste:
 Leandro Lucarella wrote:
 Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function which
 doesn't support formatting.

 C++ got around this by giving state to the iostream classes.

madness.

It's horrific but surprisingly flexible. I've created stateful formatters for various protocols and made it work all invisibly with the formatting hooks provided in C++. For example: std::cout << a << b << c << std::flush;


I think that putting formatting details in the stream is a very good idea for serialization, but not for normal textual output, the two things are not the same (even if it might be useful to use some xml serialization for some objects, and send it together with "normal" text). Fawzi
Aug 22 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
Fawzi Mohamed wrote:
 On 2008-08-22 22:10:21 +0200, Leandro Lucarella <llucax gmail.com> said:
 
 Sean Kelly, el 22 de agosto a las 12:46 me escribiste:
 Leandro Lucarella wrote:
 Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function 
 which
 doesn't support formatting.

 C++ got around this by giving state to the iostream classes.

madness.

It's horrific but surprisingly flexible. I've created stateful formatters for various protocols and made it work all invisibly with the formatting hooks provided in C++. For example: std::cout << a << b << c << std::flush;


I think that putting formatting details in the stream is a very good idea for serialization, but not for normal textual output, the two things are not the same (even if it might be useful to use some xml serialization for some objects, and send it together with "normal" text).

Yeah, the above example was a simplified version of some pretty fancy stuff I did for a multi-protocol server app. It made serialization painfully easy for the user (so long as the proper support code was built into the formatting frastructure), but was really operating well beyond the scope of what iostream formatting was intended to do. In general though I think it's preferable to have such things done differently than raw IO. Tango has some support for this with its Reader/Writer model in tango.io.protocol, but even that is somewhat limited to specific categories of protocols. For example, I recently tried using it for ASN.1 transcoding and it just isn't sufficient. Sean
Aug 22 2008
parent Fawzi Mohamed <fmohamed mac.com> writes:
On 2008-08-23 00:28:19 +0200, Sean Kelly <sean invisibleduck.org> said:

 Fawzi Mohamed wrote:
 On 2008-08-22 22:10:21 +0200, Leandro Lucarella <llucax gmail.com> said:
 
 Sean Kelly, el 22 de agosto a las 12:46 me escribiste:
 Leandro Lucarella wrote:
 Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function which
 doesn't support formatting.

 C++ got around this by giving state to the iostream classes.

madness.

It's horrific but surprisingly flexible. I've created stateful formatters for various protocols and made it work all invisibly with the formatting hooks provided in C++. For example: std::cout << a << b << c << std::flush;


I think that putting formatting details in the stream is a very good idea for serialization, but not for normal textual output, the two things are not the same (even if it might be useful to use some xml serialization for some objects, and send it together with "normal" text).

Yeah, the above example was a simplified version of some pretty fancy stuff I did for a multi-protocol server app. It made serialization painfully easy for the user (so long as the proper support code was built into the formatting frastructure), but was really operating well beyond the scope of what iostream formatting was intended to do. In general though I think it's preferable to have such things done differently than raw IO. Tango has some support for this with its Reader/Writer model in tango.io.protocol, but even that is somewhat limited to specific categories of protocols. For example, I recently tried using it for ASN.1 transcoding and it just isn't sufficient.

Yes I think that it is the correct approach to have special streams for serialization, as long as they can then be hooked to the "normal" streams then everything is ok. It is a pity that Reader/Writer are not sufficient, could it be extended to support it, or a different approach is needed? Actually my needs are smaller, I would love to have at least a textual streaming protocol (xml based?) that works with Reader/Writer for quick dump/read of my objects.. Fawzi
Aug 23 2008
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Leandro Lucarella wrote:
 Sean Kelly, el 22 de agosto a las 12:46 me escribiste:
 My experience with Java suggests that toString is meant for debugging purposes 
 anyway.  It's rare that an object will produce meaningful user-level output
with 
 its toString method.

I agree, I meant that D should do better. Like templates are for gurus in C++ and for people in D, formatting should be for people too in D (as opposed to C++ manipulators =).

I strongly favor library solutions over language solutions for this. Even if there were a language solution, I would still want a library solution so I could better enforce separation of concerns. Unless I want to use dependency injection on my domain classes, which is an Abomination unto Nuggan, or put complex formatting logic into them, which is nearly as abhorrent.
Aug 22 2008
prev sibling parent reply Don <nospam nospam.com.au> writes:
Leandro Lucarella wrote:
 Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function which
doesn't 
 support formatting.

I think is useful only for debugging purposes.

I agree. Which means that having I/O functions call toString() is a broken design (I'm looking at you, writefln!)
 
 C++ got around this by giving state to the iostream classes.

I think C++ formatting is heavily ill. All the manipulator stuff is madness.

Aug 24 2008
parent Ary Borenszweig <ary esperanto.org.ar> writes:
Don a écrit :
 Leandro Lucarella wrote:
 Don, el 18 de agosto a las 12:41 me escribiste:
 I cannot understand the rationale for a toString() member function 
 which doesn't support formatting.

I think is useful only for debugging purposes.

I agree. Which means that having I/O functions call toString() is a broken design (I'm looking at you, writefln!)

But... writefln is used a lot for debugging purposes. If you quickly want to print something to the console, it's much faster not having to use toString() everywhere.
Aug 24 2008