Possibly a poorly worded question, but here goes an example:
given these structs;
pub struct Poll {
_lat: f64,
_lon: f64,
_at: i64,
_heading: f64,
_speed: f64,
}
pub struct Waypoint {
_lat: f64,
_lon: f64,
}
and this trait;
pub trait CoordMeasure {
fn dist_to(&self, other: &Self ) -> f64;
}
how do I avoid duplicating this code like I have done?
impl CoordMeasure for Poll {
fn dist_to(&self, other: &Poll) -> f64 {
super::core::distance(self, other)
}
}
impl CoordMeasure for Waypoint {
fn dist_to(&self, other: &Waypoint) -> f64 {
super::core::distance(self, other)
}
}
I have two calls to the same function distance.
pub fn distance<T: Coord>(a: &T, b: &T ) -> f64 {
let lat1_rads = (90.0 - a.lat()).to_radians();
let lat2_rads = (90.0 - b.lat()).to_radians();
let lon_rads = (b.lon() - a.lon()).to_radians();
let cos_of_lat1 = lat1_rads.cos();
let cos_of_lat2 = lat2_rads.cos();
let sin_of_lat1 = lat1_rads.sin();
let sin_of_lat2 = lat2_rads.sin();
let cos_of_lons = lon_rads.cos();
let equation = ((cos_of_lat2 * cos_of_lat1) + (sin_of_lat2 * sin_of_lat1 * cos_of_lons)).acos();
6334009.6 * equation
}
It's just one line of code that's being repeated, but it could be more in a better example. In C# this code would be written once in an abstract class that Waypoint and Poll were derived from. What's the idiomatic Rust way of handling this situation?
Generic implementations are possible:
impl<T: Coord> CoordMeasure for T {
fn dist_to(&self, other: &T) -> f64 {
super::core::distance(self, other)
}
}
But in this particular case, you should just drop CoordMeasure
altogether and implement this on Coord
as a default method:
trait Coord {
…
fn dist_to(&self, other: &Self) -> f64 {
super::core::distance(self, other) // or move its contents in here
}
}
You might also want to make it so that it can cope with other types of other
(I don’t see any immediate reason why other
must be the same type as self
:
fn dist_to<Other: Coord>(&self, other: &Other) -> f64 {
let lat1_rads = (90.0 - self.lat()).to_radians();
let lat2_rads = (90.0 - other.lat()).to_radians();
let lon_rads = (b.lon() - self.lon()).to_radians();
let cos_of_lat1 = lat1_rads.cos();
let cos_of_lat2 = lat2_rads.cos();
let sin_of_lat1 = lat1_rads.sin();
let sin_of_lat2 = lat2_rads.sin();
let cos_of_lons = lon_rads.cos();
let equation = ((cos_of_lat2 * cos_of_lat1) + (sin_of_lat2 * sin_of_lat1 * cos_of_lons)).acos();
6334009.6 * equation
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With