Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Dynamic dispatch should be allows as long as the plot is accepting the same data points #121

Open
mlange-42 opened this issue Mar 23, 2020 · 3 comments

Comments

@mlange-42
Copy link

@mlange-42 mlange-42 commented Mar 23, 2020

If the chart is defined to accept same data type, even though the axis is using different types of decorator, those chart types should be cvt into a trait object.

====
Original issue (one of valid use case)

First, many thanks for providing this great library!

Learning Rust for 2 weeks now and not really grasping the type system yet, this may be more of a Rust question than a plotters question.

I try to create a chart context with optional log-scaled y axis:

let mut cc = if y_log {
    ChartBuilder::on(&root)
                .build_ranged(
                    (xlim.0)..(xlim.1),
                    LogRange((ylim.0)..(ylim.1)),
                ).unwrap()
} else {
    ChartBuilder::on(&root)
                .build_ranged(
                    (xlim.0)..(xlim.1),
                    (ylim.0)..(ylim.1),
                ).unwrap()
} 

Now, my problem is that this doesn't compile due to:

expected type `plotters::chart::context::ChartContext<'_, _, plotters::coord::ranged::RangedCoord<_, plotters::coord::numeric::RangedCoordf64>>`
 found struct `plotters::chart::context::ChartContext<'_, _, plotters::coord::ranged::RangedCoord<_, plotters::coord::logarithmic::LogCoord<f64>>>`

When I use the condition in build_ranged

if y_log { LogRange((ylim.0)..(ylim.1)) } else { (ylim.0)..(ylim.1) }

I get a type mismatch between std::ops::Range and plotters::coord::logarithmic::LogRange.

I understand that I probably have to specify an explicit type for cc, probably with some dyn Trait in ChartContext's generics. However, due to my still very limited Rust experience, I can't get it to work.

Many thanks for your help!

@38
Copy link
Owner

@38 38 commented Apr 2, 2020

Hmm, this is something unsupported yet. You just spotted the root cause of this.

The cc variable doesn't have a valid type, since it can not be ChartContext<RangedCoord<_, :RangedCoordf64>> and ChartContext<'_, _, RangedCoord<_, LogCoord<f64>>> at the same time.

One way to address that (not only in Rust but also other programming languages) is using dynamic dispatch, which is, in Rust term, a trait object. However, Plotters doesn't have a trait for those two types, so the compiler don't know how to do that.

One work around is to use static dispatch instead (use template function).

Hope this is helpful, and dynamic dispatch on charts with same data type should be supported. Thanks again to come up with this problem, hopefully Plotters will support dynamic dispatch i the future release.

Thanks for trying Plotters and hope you enjoy both the crate and Rust language.

I am changing this issue to a feature request if you don't mind.

Cheers!

@38 38 changed the title Handling ChartContext generics with optional log scale [Feature Request] Dynamic dispatch should be allows as long as the plot is accepting the same data points Apr 2, 2020
@mlange-42
Copy link
Author

@mlange-42 mlange-42 commented Apr 2, 2020

Many thanks for the reply!

My solution so far was complete doubling of the plotting code, as you can see here:
https://github.com/mlange-42/easy_graph/blob/master/src/ui/chart.rs#L406

Not really nice, but good to know that my limited Rust experience was not the sole reason.

And yes, I really enjoy Rust as well as plotters.

@38
Copy link
Owner

@38 38 commented Apr 2, 2020

doubling of the plotting code

Yep, you got that. To make it nicer, you can make duplicated code reusable with a template function.

That is very often used trick in both Rust and C++ I believe. Since in C++ it's also not recommended to frequently use dynamic dispatch, or AKA virtual method functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.