RE: [boost] Re: Formal review of "Output Formatters" library beginstoday

Jeff Flinn wrote:
"John Torjo" <john.lists@torjo.com> wrote in message news:414443E0.60008@torjo.com...
Dear boosters,
The FORMAL Review of "Output Formatter" library begins today, Sept 12, 2004.
1. What is your evaluation of the design?
I find the naming conventions misleading. 'outfmt' but it does io? What is an '...ob' and '...obex'? This effort at reducing verbosity is then countered as mentioned by Dave Abrahams, by the "syntactic noise".
I am going to provide more consistent names once the review period is over. I made a start at this before review, but wanted to get a more general view of peoples thoughts before sticking to any particular names. The name outfmt is legacy. Initially it only provided output, but people were interested in input as well. Xob is an "X object" and Xobex is the variant of Xob that takes < DelimeterType >, e.g. Xobex< wchar_t * >. (I don't have a better name for this and am open to suggestions).
I do like the delimiter traits objects approach to dealing with leader/trailer existence issues. Although I have not found passing "" (empty string) as the leader/trailer being a performance bottleneck since they are only performed once per range.
What about for the separator delimeter? For example: std::cout << io::formatob( vec ).format( "" );
I like the range approach, but isn't a range library coming?
Boost.Range has recently been adopted into boost. It should be fairly trivial to replace io::range with the Boost equivalent.
Will io::range be entirely compatible? My home grown range_streamer is often used with filter and transform iterators. It would be nice to use a shorter syntax like: os << range_stream( aC, lFilterFnc, "\n=\n{ ", "\n, ", "\n}" ); rather than [snip]
You mean supporting your range_streamer from within my framework? Or supporting ranged types in general (range types are supported within the framework)?
2. What is your evaluation of the implementation?
The main motivation I had for developing a similar output facility was dealing with the dangling separator when using std::copy and ostream_iterator in a consistent/performant fashion.
Your rearrangement is quite neat! It removes the duplicated test.
3. What is your evaluation of the documentation?
After reading Jonathon's IOStream documentation, my expectations have been raised. Some of the problems are due to the misleading names used in the implementation itself. Almost everything is a format_this or format_that with format methods... Perhaps an additional namespace level would alleviate some of this.
As I have mentioned above, I am going to revise the naming once the review is over, based on the comments provided here.
Missing are Motivation and Rationale sections. When/Why would someone use this library versus ostream_iterator/Tokenizer/Spirit/...
ostream_iterator does not, AFAIK, handle nested constructs like std::vector< std::list< int > >. Tokenizer is primarliy concerned with reading data back in and I'm not sure if/how it supports containers, arrays and pair/nary types. Spirit is too complex for when you want simple formatting and is only concerned with parsing (reading) data. It also adds a lot of overhead and does not fit in with the C++ I/O stream framework. Boost.Serialize does a great job, but is not very flexible in the way that the data is serialized. Regards, Reece _________________________________________________________________ Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo

On Sun, 12 Sep 2004 21:16:29 +0100, Reece Dunn wrote
Boost.Serialize does a great job, but is not very flexible in the way that the data is serialized.
This statement is incorrect. By writing a custom archiver class you can create virtually any output you want via serialization. That said, it's clearly harder to do the simple sorts of things I believe output formmaters is trying to achieve (haven't really looked at the lib yet), serialization requires the building/linking of the library, etc. So I think there's room for both... Jeff

Missing are Motivation and Rationale sections. When/Why would someone use this library versus ostream_iterator/Tokenizer/Spirit/...
ostream_iterator does not, AFAIK, handle nested constructs like std::vector< std::list< int > >. Tokenizer is primarliy concerned with reading data back in and I'm not sure if/how it supports containers, arrays and pair/nary types.
Spirit is too complex for when you want simple formatting and is only concerned with parsing (reading) data. It also adds a lot of overhead and does not fit in with the C++ I/O stream framework.
Boost.Serialize does a great job, but is not very flexible in the way that the data is serialized.
You can add this to the docs ;) Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4.0 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)

"Reece Dunn" <msclrhd@hotmail.com> wrote in message news:BAY24-F30bGLndNOLpm0009ea76@hotmail.com...
Jeff Flinn wrote:
"John Torjo" <john.lists@torjo.com> wrote in message news:414443E0.60008@torjo.com...
Dear boosters,
The FORMAL Review of "Output Formatter" library begins today, Sept 12, 2004.
1. What is your evaluation of the design?
I find the naming conventions misleading. 'outfmt' but it does io? What is an '...ob' and '...obex'? This effort at reducing verbosity is then countered as mentioned by Dave Abrahams, by the "syntactic noise".
I am going to provide more consistent names once the review period is over. I made a start at this before review, but wanted to get a more general view of peoples thoughts before sticking to any particular names. The name outfmt is legacy. Initially it only provided output, but people were interested in input as well. Xob is an "X object" and Xobex is the variant of Xob that takes < DelimeterType >, e.g. Xobex< wchar_t * >. (I don't have a better name for this and am open to suggestions).
Let's assume boost::range is in place. Range serves a much broader arena than io streaming. In effect this Output Formatter library(OutFmt) adapts a range. OutFmt embellishes or adorns the values in the range as they are sent to an output stream, and strips these adornments when retrieving a range from a stream. This leads me to think that boost::range::io would be a better organization. Some alternate names, that avoid the overuse of "format" might be derived from adornment, decoration, embellishment, ... using boost::range::io; std::cout << adorn( r, adornment( "{", "' ", " }" ) ); Where non-member function adorn, returns an adorned_range, using the specified adornment(s).
I do like the delimiter traits objects approach to dealing with leader/trailer existence issues. Although I have not found passing "" (empty string) as the leader/trailer being a performance bottleneck since they are only performed once per range.
What about for the separator delimeter? For example:
std::cout << io::formatob( vec ).format( "" );
Yes using the "adornment" syntax above.
I like the range approach, but isn't a range library coming?
Boost.Range has recently been adopted into boost. It should be fairly trivial to replace io::range with the Boost equivalent.
Will io::range be entirely compatible? My home grown range_streamer is often used with filter and transform iterators. It would be nice to use a shorter syntax like: os << range_stream( aC, lFilterFnc, "\n=\n{ ", "\n, ", "\n}" ); rather than [snip]
You mean supporting your range_streamer from within my framework? Or supporting ranged types in general (range types are supported within the framework)?
Two(ill communicated) points were intended. The first would be extending io::range with io::filtered_range, and io::transformed_range. These would have all of the existing constructors with an additional argument for the filter/transform function. I assume internally io::range calls begin/end returning the appropriate adapted iterators. I've not looked at boost::range to see if this is supported. The second point was that whatever the name, the delimiters would be specified via additional function/constructor argurment(s), rather than via the ob( c ).format( fmt ) member function call syntax. I certainly would replace my range_stream with your more general bi-directional facilities when available.
2. What is your evaluation of the implementation?
The main motivation I had for developing a similar output facility was dealing with the dangling separator when using std::copy and ostream_iterator in a consistent/performant fashion.
Your rearrangement is quite neat! It removes the duplicated test.
3. What is your evaluation of the documentation?
After reading Jonathon's IOStream documentation, my expectations have been raised. Some of the problems are due to the misleading names used in the implementation itself. Almost everything is a format_this or format_that with format methods... Perhaps an additional namespace level would alleviate some of this.
As I have mentioned above, I am going to revise the naming once the review is over, based on the comments provided here.
Missing are Motivation and Rationale sections. When/Why would someone use this library versus ostream_iterator/Tokenizer/Spirit/...
ostream_iterator does not, AFAIK, handle nested constructs like std::vector< std::list< int > >. Tokenizer is primarliy concerned with reading data back in and I'm not sure if/how it supports containers, arrays and pair/nary types.
Spirit is too complex for when you want simple formatting and is only concerned with parsing (reading) data. It also adds a lot of overhead and does not fit in with the C++ I/O stream framework.
Boost.Serialize does a great job, but is not very flexible in the way that the data is serialized.
These should all be in the documentation. Thanks, Jeff

using boost::range::io;
std::cout << adorn( r, adornment( "{", "' ", " }" ) );
This leads me to think about this: using boost::range; std::cout << write(c); std::cin >> read(c);
You mean supporting your range_streamer from within my framework? Or supporting ranged types in general (range types are supported within the framework)?
Two(ill communicated) points were intended. The first would be extending io::range with io::filtered_range, and io::transformed_range. These would
As a side note, the RangeLib (formelly, Range Template Library) has them and they work like a charm ;) I will post an update in about a week and a half. (were you talking about them?) Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4.0 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)
participants (4)
-
Jeff Flinn
-
Jeff Garland
-
John Torjo
-
Reece Dunn