
On 7/4/07, Phil Endecott <spam_from_boost_dev@chezphil.org> wrote:
Jake Voytko wrote:
plot_range(my_plot, data.begin(), data.end(), default_functor, human_age, circle, orange, red, 3, 10);
It would be great to be able to write just 'data' in place of 'data.begin(), data.end()'. Is there anything stopping this?
The STL algorithm functions are used as the basis here, and it carries all of the same benefits. First, you can select a small subset of your data if you'd like that to be plotted (for example, plotting a single year out of 100 years of data). Second, the interface itself almost completely weeds out noncompliant functions, as functions without iterator support won't compile, and the error message will (usually) show on the line in the user's code where the error is. A minor benefit is also location of compiler errors. Looking at: plot(my_plot, data, ...); Instead of giving a compiler error at the call for plot(), it would report the error inside of plot(). That's a minor issue, as it's still relatively clear why the error is occuring, but the line of the error is still not at the location of the error. And granted, the iterator interface doesn't ward this off altogether (as it's possible for functions to have a begin() and end() that returns the same data type, but not support a ++() operator. I hope that in typical usage it will automatically choose a plot style
(and I would vote for allocating colours in 'resistor colour code order', though starting with brown is not often a popular choice).
Absolutely.. this is a worst case example, a perfectionist user who wants to customize everything. Defaults is one of the things that I am working on this week, and it does drastically cut down what the user has to specify. Defaults would also be a benefit of named parameters.. users don't have to specify values they don't want to specify. Presumably the two functors are to extract the X and Y values from the
object. Having 'x' and 'y' in the names would make this clear, if this is the case.
Noted.. I was having trouble coming up with a clear name I would be interested to see how the various lambda
techniques could be used to write these functors inline.
That's a good idea. Presumably in
the case where the data is a sequence of numeric values the functor is unnecessary.
That is correct. The functors (which aren't even supported yet) are/will not be necessary unless the user wants to do something like plot a pair<double, human>. In particular, I would hope that a sequence<numeric>
would use the index as X (starting at 0 or 1?), and the value as Y, and container<std::pair<numeric,numeric>> would use pair.first as X and pair.second as Y. Right?
The pair< , > part was correct, and I will soon support sequence containers in the same fashion (I only started 2D support in the past week, so its feature set is still underdeveloped) (There are plenty of C++ users (though not
on this list) who would be put off by the concept of functors, and who would benefit from having it 'just work').
These people have the ability to just use the numeric clauses. Functor conversion is a feature that has been suggested by a few people, so I know that there is at least minimal demand. I included them in this example in order to highlight another potential problem with the plot_range() function.. needing to convert the second value of a pair< , >, but not the first So hopefully in many cases it reduces to:
plot_range(my_plot, data);
The current signature is plot_range(my_plot, data.begin(), data.end(), series_title, fill_color); but this is using the monolithic approach. I'm examining my options for the best way to expand the utility of this function, which is why I started this thread :). I think that at minimum, we need my_plot, data, and series_title, because if the user wants a legend, each series has to be called something, and requiring the user to go back and change the labels after they add a function would be awkward. When you do need to use more non-default parameters, I think that I
would use a style object like this:
plot_range(my_plot, data, plot_style(red, circle));
Since the types for the colours and point shapes are distinct you can save the user from having to remember a correct order by providing plot_style constructors with both parameter orderings. This can extend to the stroke width. But there is a problem with the fill colour; what is that? Is it for the area under the curve? Why would you want it to be different from the stroke colour? - and also for the 'size'; what is that?, because they are not distinct.
To use a square as an example, the outline of the square is the stroke, and the inside of the square is the fill. These elements apply to most SVG visual objects, so I stuck with the SVG naming convention. The difference of why you'd want it to be different than the stroke color is so that it'll show up easier.. you can have a background color of white, a stroke color of black, and a fill color of white, and get empty circles that represent your data point. Boost.Parameter does a good job when large numbers of parameters are
unavoidable. Do check on the comprehensibility of error messages and the compile time increase, as these are the most common problems (IMO) with 'advanced' things like Boost.Parameter.
Good thinking! Jake