
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers Feedback / use cases welcome ;). So far it only produces graphs in one dimension, but inch by inch it's getting better! Hopefully by the halfway point, I'll have a working legend system as well as graphs in two dimensions, and I hope to take a good chunk out of the list of suggestions that I've been given! Further into the future, I want to look at the animation / hover features that SVG has to offer to see if I can take advantage of them for data display purposes and make the output of the program awesome. Jake

Jake Voytko a écrit :
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Feedback / use cases welcome ;).
I don't like the iostreams-like interface so much. Wouldn't boost.parameter be cleaner?

I had not known about Boost.Parameter, and I feel that it can help my project out tremendously. However, I'm not ready to give up on the stream interface just yet. I feel that at a glance, it allows the programmer to make a few (correct) inferences about how the program works without ever looking at docs. 1) It gives the feel that something is being written 2) It implies that there is chaining This is also my own opinion, but I feel that code written using the stream operator also *looks* cleaner than a monolithic constructor call or style call to take care of all styling (including background color/border, title size/color/position, legend background/border/text size/position, main plot background/border color and size /plot colors / etc)before anything is written. I absolutely see the value of having the following syntax: my_plot << plot_range(data.begin(), data.end(), line_thickness=3, point_color=red, line_color=black); and I will certainly consider ways to incorporate this into my design. Jake On 6/13/07, Mathias Gaunard <mathias.gaunard@etu.u-bordeaux1.fr> wrote:
Jake Voytko a écrit :
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Feedback / use cases welcome ;).
I don't like the iostreams-like interface so much. Wouldn't boost.parameter be cleaner?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

[mailto:boost-bounces@lists.boost.org] On Behalf Of Jake Voytko <snip> This is also my own opinion, but I feel that code written using the stream operator also *looks* cleaner than a monolithic constructor call or style call to take care of all styling (including background color/border, title size/color/position, legend background/border/text size/position, main plot background/border color and size /plot colors / etc)before anything is written.
I absolutely see the value of having the following syntax:
my_plot << plot_range(data.begin(), data.end(), line_thickness=3, point_color=red, line_color=black);
I have to say that I like the streaming style interface. The only drawback that jumps out at me is that every time I look at it, it _feels_ like I would be able to do something like: svg_plot my_plot("./image.svg"); my_plot << image_size(500, 200) << x_scale(-7, 9) << draw_axis(); for (double i = 1.0; i < 10; i += 1.0) { my_plot << i; } my_plot << write(); Or can I??
Feedback / use cases welcome ;).
In my situation the data that I might want to visualize isn't directly usable (well, meaningful) without interpolation between the data points. With the combination of the extractor suggested by Matias and support for SVG's Bézier curves then I could output a plot that is more representative of the actual data. I'd also like to second Paul Bristow's suggestion for auto scaling, if I already knew what was in the container then why would I need to "visualize it" :-} Matt Scanned by McAfee GroupShield {X3BTB534}

On 6/13/07, Matt Doyle <mdoyle@a-m-c.com> wrote:
I have to say that I like the streaming style interface. The only drawback that jumps out at me is that every time I look at it, it _feels_ like I would be able to do something like:
svg_plot my_plot("./image.svg");
my_plot << image_size(500, 200) << x_scale(-7, 9) << draw_axis(); for (double i = 1.0; i < 10; i += 1.0) { my_plot << i; } my_plot << write();
Or can I??
Currently, no. However, I don't see why I couldn't add that before my midterm release in July :)
Feedback / use cases welcome ;).
In my situation the data that I might want to visualize isn't directly usable (well, meaningful) without interpolation between the data points. With the combination of the extractor suggested by Matias and support for SVG's Bézier curves then I could output a plot that is more representative of the actual data. I'd also like to second Paul Bristow's suggestion for auto scaling, if I already knew what was in the container then why would I need to "visualize it" :-}
I haven't gotten a chance to look at the Bézier curves yet that SVG supports. The look is definitely something that I'd want to allow people to have ( sin(x) would look pretty hideous without a large number of points). And Paul and Matias' suggestions are part of my vision for how this project will end up, so don't worry about that :)

Jake Voytko wrote:
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Re: Boost.Parameter, excellent for managing operations that have lots of options, but I still like the streaming interface :-) For options like draw_axis() can we ditch the paranthesis - unless you're planning on adding options to it later? Likewise, why do we need to write() operation? Can't we just use << std::flush if we want to flush to file, otherwise you can flush to file when the object goes out of scope, or when it's close() member function is called (if it has one). cf the iostreams. Otherwise looks like it's progressing nicely. HTH, John.

John Maddock ha escrito:
Jake Voytko wrote:
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Re: Boost.Parameter, excellent for managing operations that have lots of options, but I still like the streaming interface :-)
For options like draw_axis() can we ditch the paranthesis - unless you're planning on adding options to it later?
Likewise, why do we need to write() operation? Can't we just use << std::flush if we want to flush to file[...]
Because svg_plot is not an std::ostream? Or do you mean svg_plot should emulate std iostreams and re-use some of its manipulators? Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

On 6/13/07, John Maddock <john@johnmaddock.co.uk> wrote:
For options like draw_axis() can we ditch the paranthesis - unless you're planning on adding options to it later?
I am.. I left the shell there so that I could put down a basic prototype of what I'd be doing so that I could come back to it later and flesh it out. Likewise, why do we need to write() operation? Can't we just use <<
std::flush if we want to flush to file, otherwise you can flush to file when the object goes out of scope, or when it's close() member function is called (if it has one). cf the iostreams.
I chose a write() function because of the "Design and Programming" section of the "Requirements and Guideline" page states that explicit is better than implicit, and this seemed like the most explicit way to do this! I also like the idea by Phil Endicott for using the write function to specify a file to use for writing (or a stream). Later when I have more time, I'll play around with various ideas of this nature and see which seems to work best. Otherwise looks like it's progressing nicely. Thank you =)

on Wed Jun 13 2007, "John Maddock" <john-AT-johnmaddock.co.uk> wrote:
Jake Voytko wrote:
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Re: Boost.Parameter, excellent for managing operations that have lots of options, but I still like the streaming interface :-)
Me too :) -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Feedback / use cases welcome ;).
From your example on the wiki: svg_plot my_plot("./image.svg"); my_plot << image_size(500, 200) << x_scale(-7, 9) << draw_axis() << plot_range(data1.begin(), data1.end(), blue) << plot_range(data2.begin(), data2.end(), green) << write(); I would suggest: svg_plot my_plot; my_plot.set_image_size(500,200); my_plot.set_x_scale(-7,9); my_plot.draw_axis(); my_plot.plot(data1, blue); my_plot.write("./image.svg"); i.e. - I don't think that operator overloading of << adds enough to be justified. - Large numbers of constructor parameters are confusing unless you use named parameters, which are themselves sufficiently unusual that they are non-intuitive. I suggest avoiding constructor parameters when possible and using e.g. set_* methods instead. - Make it possible to plot an entire container more simply than specifying both begin and end iterators. If you feel the need to make the style more compact, it should be possible to return a reference to the plot and chain methods like this: my_plot.set_image_size(500,200) .set_x_scale(-7,9) .draw_axis() .plot(data1, blue) .write("./image.svg"); - though I haven't tried to do this recently, so maybe I have forgotten some detail. You might like to look at how GIL specifies colours, to see if there is anything that you can re-use. At least, you should make sure that you don't implement something that is similar-but-not-quite-the-same for colour names. The results look great, by the way. I was doing something with Gnuplot the other night that would have benefited from something like this: http://chezphil.org/tmp/fanplot.png I think that a simple wrapper program around your library that can read and plot CSV files would be most useful. Regards, Phil.

on Wed Jun 13 2007, "Phil Endecott" <spam_from_boost_dev-AT-chezphil.org> wrote:
If you feel the need to make the style more compact, it should be possible to return a reference to the plot and chain methods like this:
my_plot.set_image_size(500,200) .set_x_scale(-7,9) .draw_axis() .plot(data1, blue) .write("./image.svg");
Phil makes good points in this post. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Wed Jun 13 2007, "Phil Endecott" <spam_from_boost_dev-AT-chezphil.org> wrote:
If you feel the need to make the style more compact, it should be possible to return a reference to the plot and chain methods like this:
my_plot.set_image_size(500,200) .set_x_scale(-7,9) .draw_axis() .plot(data1, blue) .write("./image.svg");
Phil makes good points in this post.
I second that. My 0.02€: I'd favor the "common" way to do it, i.e. set-functions, rather than having your users learn a new "cute-ish" scheme with stream ops to just set some values. Additionally: how does one use boost::bind with stream operator functions? bind(operator<<(..), my_plot, bind(set_x_scale(), _1, _2)) ? Cheers, /Marcus

As far as the set vs. stream debate goes, I'm going to do a little more work with streams and then post a request for people to look at it per Paul Bristow's suggestion. I'll present pros and cons and get input and see if there's enough reason to switch. I still prefer the stream method, though ;) I'm not near a compiler right now, so I can't comment. I'm not going to give an example with Boost.Bind without checking to see if it's right! Jake On 6/14/07, Marcus Lindblom <macke@yar.nu> wrote:
David Abrahams wrote:
on Wed Jun 13 2007, "Phil Endecott" <spam_from_boost_dev-AT-chezphil.org> wrote:
If you feel the need to make the style more compact, it should be possible to return a reference to the plot and chain methods like this:
my_plot.set_image_size(500,200) .set_x_scale(-7,9) .draw_axis() .plot(data1, blue) .write("./image.svg");
Phil makes good points in this post.
I second that.
My 0.02€: I'd favor the "common" way to do it, i.e. set-functions, rather than having your users learn a new "cute-ish" scheme with stream ops to just set some values.
Additionally: how does one use boost::bind with stream operator functions? bind(operator<<(..), my_plot, bind(set_x_scale(), _1, _2)) ?
Cheers, /Marcus
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jake Voytko Sent: 13 June 2007 03:01 To: boost@lists.boost.org Subject: [boost] Progress of Boost.SVG_Plot
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Feedback / use cases welcome ;). So far it only produces graphs in one dimension, but inch by inch it's getting better! Hopefully by the halfway point, I'll have a working legend system as well as graphs in two dimensions, and I hope to take a good chunk out of the list of suggestions that I've been given! Further into the future, I want to look at the animation / hover features that SVG has to offer to see if I can take advantage of them for data display purposes and make the output of the program awesome.
Looking rather good already :-)) Though I suspect that people will have a clearer idea of the implications of the parameters v. stream debate when we have a slightly fuller example with axes ticks and labels and title etc. Perhaps when you have a bit more fleshed out, you can repost with a title like: "Progress of Boost.SVG_Plot - request for views on how to present the graph options." Personally, I still don't like the use of << at all. The set functions feel much more intuitive to me, and chaining provides a shortcut if you want, but you don't have to use it. Once you have an example, it's pretty obvious how to use it. It avoids the need to chose short names for my_plot to cut down repetition. Does "output" feels better than "write"? No - perhaps write is OK? my_plot.output("my_image.svg") also feels right to me. And this actually does the output to file (or elsewhere). This seems right so you can say: svg_plot my_plot; my_plot.set_image_size(500,200); my_plot.set_x_scale(-7,9); my_plot.draw_axis(); my_plot.plot(data1, blue); my_plot.write("./image.svg"); my_plot.plot(data1, red); my_plot.set_image_size(5000,2000); my_plot.write("./big_image.svg"); to get more than one plot? Keep up the good work :-) Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Paul A Bristow ha escrito:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jake Voytko Sent: 13 June 2007 03:01 To: boost@lists.boost.org Subject: [boost] Progress of Boost.SVG_Plot
For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Feedback / use cases welcome ;). So far it only produces graphs in one dimension, but inch by inch it's getting better! Hopefully by the halfway point, I'll have a working legend system as well as graphs in two dimensions, and I hope to take a good chunk out of the list of suggestions that I've been given! Further into the future, I want to look at the animation / hover features that SVG has to offer to see if I can take advantage of them for data display purposes and make the output of the program awesome.
Looking rather good already :-))
Though I suspect that people will have a clearer idea of the implications of the parameters v. stream debate when we have a slightly fuller example with axes ticks and labels and title etc. Perhaps when you have a bit more fleshed out, you can repost with a title like:
"Progress of Boost.SVG_Plot - request for views on how to present the graph options."
Personally, I still don't like the use of << at all.
The set functions feel much more intuitive to me, and chaining provides a shortcut if you want, but you don't have to use it.
I think there's an advantage to the << interface that hasn't been mentioned yet: << allows extensibility in the sense that further elements can be seamlessly incorporated in the future without modifying svg_plot public interface. For instance: svg_plot& operator<<(svg_plot& p,const triangle& t) { return p<<line(...)<<line(...)<<line(...); } ... svg_plot my_plot; my_plot<<triangle(...); Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Joaquín Mª López Muñoz Sent: 13 June 2007 18:14 To: boost@lists.boost.org Subject: Re: [boost] Progress of Boost.SVG_Plot
Personally, I still don't like the use of << at all.
The set functions feel much more intuitive to me, and chaining provides a shortcut if you want, but you don't have to use it.
I think there's an advantage to the << interface that hasn't been mentioned yet: << allows extensibility in the sense that further elements can be seamlessly incorporated in the future without modifying svg_plot public interface. For instance:
svg_plot& operator<<(svg_plot& p,const triangle& t) { return p<<line(...)<<line(...)<<line(...); }
...
svg_plot my_plot; my_plot<<triangle(...);
perhaps you can expand on this? 1 What is the value in avoiding modifying the public interface? Looking towards standards? 2 Can it not be done other ways? p.line(t1,t2).line(t2,t3).line(t3,t1)? 3 Are the set and stream methods mutually exclusive? 4 Could this be used even if the set method was used for other parameters? Thanks. Paul PS Opinions are clearly divided on this issue. Should we try to get more views from elsewhere? But I don't want it to become a bikeshed issue ;-) Anyway, showstopper/killer issues will probably emerge before too long in the project. --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

On 6/15/07, Paul A Bristow <pbristow@hetp.u-net.com> wrote:
svg_plot& operator<<(svg_plot& p,const triangle& t) { return p<<line(...)<<line(...)<<line(...); }
...
svg_plot my_plot; my_plot<<triangle(...);
perhaps you can expand on this?
1 What is the value in avoiding modifying the public interface? Looking towards standards?
Last night, I was playing around with the implications of what Joaquín said / looking through feature requests, and I came up with an example of a function that solves a request of yours (a way to save settings you would frequently use) with no extra work on the interface: //BEWARE! experimental syntax, and not an actual tested example. // in user_header.hpp enum svg_user_customization { my_initial_style, ... }; svg_plot& operator<<(svg_plot& p, svg_user_customization val) { switch(val) { case my_initial_style: p << image_size (800, 600) << show_axis << x_axis_color( blue ) << y_axis_color( darkgray ) << x_axis_major_tick_color( gray) << y_axis_major_tick_color( darkgray ) << x_axis_minor_tick_color( gray ) << y_axis_minor_tick_color( gray ) << show_background_border << background_border_color ( darkgray ) << background_border_thickness( 5 ) << background_color ( lightblue ) // ... you get the point. This could go on for pages. break; } return p; } // in user_program.cpp int main() { svg_plot my_plot; my_plot << my_initial_style; // work } // end program As far as avoiding modifying the interface, it'll simply make the program less prone to bugs, it'll be less to test, it'll be less for future maintainers to worry about breaking regressions for, and most importantly, it's extensible. As long as you can reduce an operation to commands supported by the svg_plot or svg interface, you can implement it once and use it as many times as you want. 2 Can it not be done other ways? p.line(t1,t2).line(t2,t3).line(t3,t1)? Using the triangle example for the svg class, I don't think that there's any way using basic C++ syntax to do this within a function call. (I'm not familiar enough with template metaprogramming to make a statement to that effect) 3 Are the set and stream methods mutually exclusive? No, they can exist at the same time. There's no good reason a class couldn't support both. The only question I have is whether or not that would be good programming practice (to maintain the header, you'd have to make the same changes to the interface to both the set_ and << functions) 4 Could this be used even if the set method was used for other parameters? Yes. However, combining my answers for #1 and #3, I think it would be best to keep them all in the stream interface. PS Opinions are clearly divided on this issue. Should we try to get more
views from elsewhere?
I'm open to anything. Do you have any ideas, or alternate locations we can go? Thank you for your time! Jake

// in user_header.hpp enum svg_user_customization { my_initial_style, ... };
svg_plot& operator<<(svg_plot& p, svg_user_customization val) { switch(val) { case my_initial_style:
[...] } }
// in user_program.cpp int main() { svg_plot my_plot; my_plot << my_initial_style;
// work }
// end program
Is there a raison to use an enumeration instead of a 'tag' type for selecting the implementation? (if I am not clear, an example follow) using a type would need to use () but can probably be more powerful. An example: Class MyStyle { Public: Explicit MyStyle(float BgClr):m_bg_clr(BgClr) {} Float get BgClr() {...} Protected: float m_bg_clr; }; Class AnotherStyle {}; svg_plot& operator<<(svg_plot& p, MyStyle val) { p << axis_on << color(val.getBgClr()) << ... } svg_plot& operator<<(svg_plot& p, AnotherStyle) { p << axis_off } Int main() { P << MyStyle(0.7) << plot(); P << AnotherStyle() << truc; MyStyle s1(0.2); P << s1 << somethings; }
2 Can it not be done other ways? p.line(t1,t2).line(t2,t3).line(t3,t1)?
We want the primitive (Triangle here) to be user defined, isn't it? We could have p.add<Triangle>(t1,t2,t3); or p.add(Triangle(t1,t2,t3)); or p.add<Triangle>(t1)(t2)(t3); but I don't really see the advantage over stream based interface.
3 Are the set and stream methods mutually exclusive? programming practice (to maintain the header, you'd have to make the same changes to the interface to both the set_ and << functions)
One can call the other but the argument type would need to be duplicated
4 Could this be used even if the set method was used for other parameters?
Yes. However, combining my answers for #1 and #3, I think it would be best to keep them all in the stream interface.
Personally, I found the streaming interface for adding object pretty good. But I like the setter interface better for customizing the svg_plot. But it isn't a very important choice in my eyes. -- Cédric Venet

Jake Voytko wrote:
p << image_size (800, 600) << show_axis << x_axis_color( blue ) << y_axis_color( darkgray ) << x_axis_major_tick_color( gray) << y_axis_major_tick_color( darkgray ) << x_axis_minor_tick_color( gray ) << y_axis_minor_tick_color( gray ) << show_background_border << background_border_color ( darkgray ) << background_border_thickness( 5 ) << background_color ( lightblue )
I not at all keen on this. I'll try to explain why. Consider any of the textbook examples of classes, and how they can (or can't) be extended: - I want something that's like std::string, but I'd really like to be able to have void std::string::toLowerCase(void) { .... } - I want something like textbook::animal, but I need bool textbook::animal::has_four_legs() { return num_legs()==4; } - I want something like textbook::solidshape, but I need int num_holes_through_shape(void) { .... } - I want something like mylibrary::Date, but I need dayofweek mylibrary::Date::day_that_month_started_on() { ..... } So wanting to take a class and extending it is very common, and in the cases of interest these extensions are all things that can be implemented using the public interface of the existing class. There are basically two ways in which it can be done: 1. Create your own subclass which inherits from the thing you're trying to extend and adds the new methods. This gets a bit tricky if you want to add multiple independent methods to the same base class, and any methods in the base class that return things of their own type will return the base class not the subclass. So it's probably not the right thing to do in many cases. 2. Write free functions instead of methods. i.e. instead of writing if (the_animal.has_four_legs()) { ... } you have to write if (has_four_legs(the_animal)) { ... } The only real problem with this way is the you have to remember whether each 'method' is a real method of the base class or a free function. One option for a class that expects to be extended is to put *everything* in free functions, having a minimal set of invariant-preserving public methods that access the private data. (You can even do without them using friend declarations.) Let's think about iostreams for a moment. There the need is to be able to extend the ostream class with new methods for formatted output of new types. Essentially what it does is: ostream strm(fn); int i; char c; std::string s; somo_other_type z; write(strm,i); write(strm,c); write(strm,s); write(strm,z); i.e. free functions for each extension, except that the library designers chose not to use a conventional function name like 'write', but instead chose operator<<. Is this a good choice? Well, there is a famous quote somewhere (would anyone like to remind me who it was) something like "well I gave up on C++ when I saw them doing a left shift on the standard output". It's a jokey quote, but adding extra "magic" syntax is something that makes what's really going on in the program less transparent. It doesn't take at all long for someone to learn that A.B(C) means "pass C as the parameter to method B of object A" (and it helps that it is essentially the same in most OO languages). But you need to get a lot further in to your textbook to understand what is really going on when you write A<<B<<C. Of course the advantage of operator overloading is that the code can be a bit sorter. In the case of iostreams, the library is widely used and early-learnt, and so some increased learning curve has been traded off against saved keystrokes. Now to your code:
p << image_size (800, 600) << show_axis << x_axis_color( blue ) << y_axis_color( darkgray ) << x_axis_major_tick_color( gray) << y_axis_major_tick_color( darkgray ) << x_axis_minor_tick_color( gray ) << y_axis_minor_tick_color( gray ) << show_background_border << background_border_color ( darkgray ) << background_border_thickness( 5 ) << background_color ( lightblue )
My first impression on seeing that is that this _is_ the iostreams overloading of operator<<. For example, a library that rendered text into a bitmap image might subclass ostream so that you could write: bitmap_text_buffer b; int i; some_type_with_operator<<_defined X; b << at(50,50) << "hello world" << X; My second impression is that your class is some sort of non-iostream stream and that each '<<something' is putting something into the stream. (SVG is XML, so maybe each one is adding an element to the XML output.) But no, on further inspection it isn't even doing that: the plot class does not behave as a stream. In fact you're using << purely as a way to save keystrokes. You're just using A<<B(C) as shorthand for B(A,C). In fact it would actually be less confusing to use a different operator: p % image_size (800, 600) % show_axis % x_axis_color( blue ) % y_axis_color( darkgray ) % x_axis_major_tick_color( gray) % y_axis_major_tick_color( darkgray ) % x_axis_minor_tick_color( gray ) % y_axis_minor_tick_color( gray ) % show_background_border % background_border_color ( darkgray ) % background_border_thickness( 5 ) % background_color ( lightblue ) ('operator,' anyone?) So let me write it out in full, as I would probably implement it: image_size (p, 800, 600); show_axis(p); x_axis_color(p, blue ); y_axis_color(p, darkgray ); x_axis_major_tick_color(p, gray); y_axis_major_tick_color(p, darkgray ); x_axis_minor_tick_color(p, gray ); y_axis_minor_tick_color(p, gray ); show_background_border(p); background_border_color (p, darkgray ); background_border_thickness(p, 5 ); background_color (p, lightblue ); Now what is so special about this particular library that that isn't good enough? (Please don't tell me that "it doesn't look as nice". Looking good is not what programs should be judged by.) In summary: - You don't need to overload operator<< to make your class extensible. - Operator overloading makes the library harder to learn because what's going on is less transparent. Regards, Phil.

Phil, That's certainly the most influential I've received against the idea of implementing the program as a stream interface. However, I think you and I prioritize our design decisions differently, as I'll explain below. I'm going to need to mull over this thread, and I'll take Paul Bristow's suggestion and put up all of the candidates under a new thread under the title "Request for views on how to present.." to get final thoughts on the matter before I make a decision. On 6/15/07, Phil Endecott <spam_from_boost_dev@chezphil.org> wrote:
2. Write free functions instead of methods. i.e. instead of writing if (the_animal.has_four_legs()) { ... } you have to write if (has_four_legs(the_animal)) { ... } The only real problem with this way is the you have to remember whether each 'method' is a real method of the base class or a free function. One option for a class that expects to be extended is to put *everything* in free functions, having a minimal set of invariant-preserving public methods that access the private data. (You can even do without them using friend declarations.)
I think if I were going this route (and I'm starting to see its merits, but more on that in a second), I would have all "set" functions that work in a chaining manner, and if I wanted to extend functionality as above, do as follows: void my_settings(svg_plot& plot) { my_plot . set_axis_color() . set_axis_line_width() . set_axis_line_style() // snip } Let's think about iostreams for a moment. There the need is to be able
to extend the ostream class with new methods for formatted output of new types. Essentially what it does is:
ostream strm(fn); int i; char c; std::string s; somo_other_type z; write(strm,i); write(strm,c); write(strm,s); write(strm,z);
i.e. free functions for each extension, except that the library designers chose not to use a conventional function name like 'write', but instead chose operator<<. Is this a good choice? Well, there is a famous quote somewhere (would anyone like to remind me who it was) something like "well I gave up on C++ when I saw them doing a left shift on the standard output". It's a jokey quote, but adding extra "magic" syntax is something that makes what's really going on in the program less transparent. It doesn't take at all long for someone to learn that A.B(C) means "pass C as the parameter to method B of object A" (and it helps that it is essentially the same in most OO languages). But you need to get a lot further in to your textbook to understand what is really going on when you write A<<B<<C.
Here is where we fundamentally disagree. It seems that you're saying (though you don't explicitly pass judgement, so I apologize if I take this the wrong way), that overloading the left shift operator for streams is a bad design because it does not stick with the de-facto standard class interface. However, when I switched from C to C++ in high school, (don't ask me why I started with C.. it wasn't an informed decision, and I certainly would have been better off learning it second ;D) I was struck by the syntax for the output and input. It was efficient and elegant compared to C calls (and compared to the boiled-down version above), everything that syntax should strive to be. Yes, I had to put in a little extra work with understanding underneath the hood how it worked, but I felt that it significantly aided my productivity once I got it. That was why I initially agreed with John Maddock's suggestion of providing it as a stream interface.. I felt that it made the learned user more productive, and the interface more easily extensible (though I forgot about this point until Joaquín Muñoz brought it up again) and elegant, at the cost of stumbling through an initially unfamiliar syntax. I agree with your statement that this isn't about looks. I will, however, split hairs and say that aesthetics do matter.. the difference between an iPod and, well, any other music player. Not that my header gets 5 stars in the interface department, and the << idea may be a miss, but I think experimenting with syntax in pursuit of that goal isn't completely misguided. As you show, the <<() operator doesn't just carry with it positive implications that I'd like it to have. So let me write it out in full, as I would probably implement it:
image_size (p, 800, 600); show_axis(p); x_axis_color(p, blue ); y_axis_color(p, darkgray ); x_axis_major_tick_color(p, gray); y_axis_major_tick_color(p, darkgray ); x_axis_minor_tick_color(p, gray ); y_axis_minor_tick_color(p, gray ); show_background_border(p); background_border_color (p, darkgray ); background_border_thickness(p, 5 ); background_color (p, lightblue );
Now what is so special about this particular library that that isn't good enough?
I think that this question is the wrong question to ask. The real question in my playbook is "What's so special about your syntax that it solves your problem better than does the standard syntax?" I feel that being able to write, literally, my_plot << my_usual_settings << hide_axis(); is powerful stuff, and is more elegant than writing my_usual_settings( my_plot ); my_plot.hide_axis(); In summary:
- You don't need to overload operator<< to make your class extensible.
I don't know where my brain was earlier, but I agree with that. - Operator overloading makes the library harder to learn because what's
going on is less transparent.
I also agree. However, the operator overloading isn't purely a design based on my excessive malace towards the learning curve of my potential users :) Don't view this post as a rebuff against your ideas, as they are grounded on solid principles, worth consideration, and are backed up by what appears to be a majority consensus. But as for now, I think the best thing is to wait until this is a little further along so there's more to show (All of the proposed changes look like they could be done in a few hours with a few cups of coffee and some vinyl records blasting). Thank you for your time, Jake

On Friday 15 June 2007 21:34, Jake Voytko wrote:
I think if I were going this route (and I'm starting to see its merits, but more on that in a second), I would have all "set" functions that work in a chaining manner, and if I wanted to extend functionality as above, do as follows:
void my_settings(svg_plot& plot) { my_plot . set_axis_color() . set_axis_line_width() . set_axis_line_style() // snip }
I've never understood why this kind of syntax is a good idea. program_options uses it and I think it just confuses new users. What's the advantage over individual function calls as Phil and others have suggested? I'm not passing judgement on the streaming-like interface. Just wondering why "overloading operator.()" is good for anything. -Dave

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David A. Greene Sent: 16 June 2007 05:07 To: boost@lists.boost.org Subject: Re: [boost] Progress of Boost.SVG_Plot
On Friday 15 June 2007 21:34, Jake Voytko wrote:
I think if I were going this route (and I'm starting to see its merits, but more on that in a second), I would have all "set" functions that work in a chaining manner, and if I wanted to extend functionality as above, do as follows:
void my_settings(svg_plot& plot) { my_plot . set_axis_color() . set_axis_line_width() . set_axis_line_style() // snip }
I've never understood why this kind of syntax is a good idea. program_options uses it and I think it just confuses new users.
What's the advantage over individual function calls as Phil and others have suggested?
Using the .axis_width().axis_color saves typing (and makes it is more compact and perhaps clearer by grouping things together). It is entirely optional - novice users can (should?) just use myplot.axis_width(); myplot.axis_color(); ... Paul

On 6/16/07, Paul A Bristow <pbristow@hetp.u-net.com> wrote:
I've never understood why this kind of syntax is a good idea. program_options uses it and I think it just confuses new users.
What's the advantage over individual function calls as Phil and others have suggested?
Using the .axis_width().axis_color saves typing (and makes it is more compact and perhaps clearer by grouping things together).
It is entirely optional - novice users can (should?) just use
myplot.axis_width(); myplot.axis_color(); ...
Paul
Exactly.. I would also organize the documentation to have an "Advanced User" section where I would include this, so users looking at the docs see only the traditional way, for lack of a better term. Users that take the time to go through the documentation (or see themselves as advanced users) would find this out, and people who are just looking through the rest of the documentation would see method calls being used without chaining, which wouldn't frighten them. Jake

On Saturday 16 June 2007 05:44, Paul A Bristow wrote:
What's the advantage over individual function calls as Phil and others have suggested?
Using the .axis_width().axis_color saves typing (and makes it is more compact
This is a poor reason to choose a design. I don't spend most of my time typing. I spend most of it maintaining what's already been written, and clarity is king.
and perhaps clearer by grouping things together).
I'm not convinced. Function calls can be grouped just as well.
It is entirely optional - novice users can (should?) just use
myplot.axis_width(); myplot.axis_color();
Ooh, multiple interfaces are about the worst thing you can do. TIMTOWTDI in my mind is what makes Perl code unmaintainable. -Dave

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David A. Greene Sent: 17 June 2007 01:45 To: boost@lists.boost.org Subject: Re: [boost] Progress of Boost.SVG_Plot
On Saturday 16 June 2007 05:44, Paul A Bristow wrote:
What's the advantage over individual function calls as Phil and others have suggested?
Using the .axis_width().axis_color saves typing (and makes it more compact and allows grouping)
This is a poor reason to choose a design. I don't spend most of my time typing. I spend most of it maintaining what's already been written, and clarity is king.
Well it's your choice, but in C++ there are lots of examples of making things shorter to make them clearer (for example, not using operator+(a, b) ;-) Paul PS The IS a downside to chaining though - it means that one can't use the name for a getter function - you can't get myplot.axis_color() to return the color. But I doubt if this is useful in this application - one is setting the plot parameters.

From: Paul A Bristow
PS There IS a downside to chaining though - it means that one can't
use
the name for a getter function - you can't get myplot.axis_color() to return the color. Yes you can. You just have two overloads:
color axis_color() const; // Getter. plot& axis_color(color newColor); // Chainable setter. -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Martin Bonner Sent: 18 June 2007 14:49 To: boost@lists.boost.org Subject: Re: [boost] Progress of Boost.SVG_Plot
From: Paul A Bristow
PS There IS a downside to chaining though - it means that one can't
use
the name for a getter function - you can't get myplot.axis_color() to return the color. Yes you can. You just have two overloads:
color axis_color() const; // Getter. plot& axis_color(color newColor); // Chainable setter.
Doh - of course. Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

on Fri Jun 15 2007, "Jake Voytko" <jakevoytko-AT-gmail.com> wrote:
I think if I were going this route (and I'm starting to see its merits, but more on that in a second), I would have all "set" functions that work in a chaining manner, and if I wanted to extend functionality as above, do as follows:
void my_settings(svg_plot& plot) { my_plot . set_axis_color() . set_axis_line_width() . set_axis_line_style() // snip }
This is exactly what Boost.Parameter is for. Only it's much, much better :-) -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

On 6/13/07, Paul A Bristow <pbristow@hetp.u-net.com> wrote:
Looking rather good already :-))
Though I suspect that people will have a clearer idea of the implications of the parameters v. stream debate when we have a slightly fuller example with axes ticks and labels and title etc. Perhaps when you have a bit more fleshed out, you can repost with a title like:
"Progress of Boost.SVG_Plot - request for views on how to present the graph options."
Personally, I still don't like the use of << at all.
The set functions feel much more intuitive to me, and chaining provides a shortcut if you want, but you don't have to use it. Once you have an example, it's pretty obvious how to use it. It avoids the need to chose short names for my_plot to cut down repetition.
The stream vs. member function discussion seems to be quite a dividing point! As Joaquín points out (and I had at one point envisioned, and subsequently forgot) , there are clear advantages as far as extensibility/readability goes, and again, I don't want to give it up quite yet if it helps make the program more extensible (with an easy-to-read syntax). However, a lot of people just don't seem comfortable with the idea of the streams. Could I just provide both? There's no obvious roadblock as far as implementation goes. The only question that remains in my mind is, "is that good programming practice?" Does "output" feels better than "write"? No - perhaps write is OK?
my_plot.output("my_image.svg") also feels right to me.
I think that's just a preference thing, and I personally like "write" better than "output". If this is a sticking point with a lot of people, I'll do the find replace :) Jake

From: Jake Voytko
The stream vs. member function discussion seems to be quite a dividing point!
Could I just provide both? There's no obvious roadblock as far as implementation goes. The only question that remains in my mind is, "is that good programming practice?"
Does "output" feels better than "write"? No - perhaps write is OK?
my_plot.output("my_image.svg") also feels right to me.
I think that's just a preference thing, and I personally like "write" better than "output". If this is a sticking point with a lot of
<pulls face> Providing two interfaces because you couldn't decide on the right one doesn't sound right to me. [warning: quoting looks wrong here] people,
I'll do the find replace :)
For both write/output and <</set, I suggest that you remember boost is not a democracy. Each library has its own dictator (in this case, you), and the only real power the rest of us have is to reject your library. I find it almost inconceivable that a useful library to generate SVG graphics would be rejected because an interface function is called "write" rather than "output". The main point is to concentrate on making the library actually useful. Don't read this as discouraging you from trying to reach a concensus on interface matters; just remember that if you can't, /you/ get to choose. (Except of course that you should obviously change from << to set.. :-) -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

On 6/14/07, Martin Bonner <Martin.Bonner@pi-shurlok.com> wrote:
<pulls face> Providing two interfaces because you couldn't decide on the right one doesn't sound right to me.
Me either. It would make maintenance that much harder. However, it *is* a potential compromise. For both write/output and <</set, I suggest that you remember boost is
not a democracy. Each library has its own dictator (in this case, you), and the only real power the rest of us have is to reject your library. I find it almost inconceivable that a useful library to generate SVG graphics would be rejected because an interface function is called "write" rather than "output". The main point is to concentrate on making the library actually useful.
Thanks for the advice. I know that I can't please all of the people all of the time (after all, it's one of my father's favorite sayings!). But in addition to making this library useful, I'd also like to see it used. If I get enough of a demand for something, I'm not against reviewing the ideas. I've gotten a lot of good suggestions from quite a few erudite individuals, and these suggestions have all shaped the project for the better. I'm not against reviewing a common concern. (Except of course that you should obviously change from << to set.. :-) We shall see what the future holds!

For those who have put time or energy into making suggestions for the SVG_Plot program, an update (with pretty pictures!) is on the wiki: http://svn.boost.org/trac/boost/wiki/soc/2007/VisualizationOfContainers
Feedback / use cases welcome ;).
Hi, This question has probably already been answered when defining the subject, but I wasn't there. So if you don't mind: Why does this library export is graph only in SVG? I have nothing against SVG but (for example): - the picture on the wiki didn't show up correctly event after I installed a plugin, I needed to clic on it for them to display on a lank page (I use IE7, like a majority of users). Also, I took the plugin from adobe and it seems they don't plan to support it anymore after the end of the year. - If I want to put the svg in a latex document, I would need to convert it to ps/eps. It would be easier to output directly in ps format. - If I want to display the graph on the screen at runtime, it would be difficult. I think this library would be a lot more useful if it allowed multiple/user customized backend. Even if the only provided backend is svg. I read the code and actually, the output is completely bound to the drawing element. Since the drawing element are already a hierarchy of class, we would need to use double dispatch, either dynamically using a visitor pattern (for example) or statically by templatifying all the drawing element with a class containing the implementation of the output. I don't think the runtime speed would be noticeably be affected by this. Just my own opinion. I really think that developing all the framework for only outputting svg is a waste. Moreover since the change to the code would be minimal if done now. Use case: - with eps backend => latex document - with GDI or openGL backend => runtime plotting - raster backend => solid image (png, jpeg) Lastly, please excuse my poor English. I don't use English very often. -- Cédric Venet Student at Centrale Paris
participants (12)
-
Cédric Venet
-
David A. Greene
-
David Abrahams
-
Jake Voytko
-
Joaquín Mª López Muñoz
-
John Maddock
-
Marcus Lindblom
-
Martin Bonner
-
Mathias Gaunard
-
Matt Doyle
-
Paul A Bristow
-
Phil Endecott