Dear rust people,
I'm a novice of Rust and trying to test the limits of my understanding of the language, so bear with me if this code is very stupid and/or non-idiomatic within Rust.
Coming from a science background and working with Python, I'm used to methods like .sort()
working out-of-the-box on a dynamic array containing numbers. Now while working in Rust I've come to learn there are inherent difficulties sorting mutable vectors containing floats. While I found that one can use .sort()
for Vec<i32>
and the like, and .sort_by(f64::total_cmp)
for Vec, I have attempted to make a generic do_sort()
method which works on vectors of any type of number Type:
6 // Custom trait for all types that can be sorted with .sort()
7 pub trait CanSort: std::cmp::Ord {}
8
9 impl CanSort for i32 {}
10 impl CanSort for u32 {}
11 impl CanSort for i64 {}
12 impl CanSort for u64 {}
13 //impl CanSort for char {} // you rarely work with Vec<char>, instead it's commonly Vec<&str>
14 //impl CanSort for &str {} // may not want to accept &str as this can fail during conversion to f64, and requires extra code
15
16 // Let's first implement a trait that will be common for all our array slices with numbers:
17 pub trait CustomSort {
18 fn do_sort(&mut self);
19 }
20
21 // All Types which implement Ord use self.sort()
22 impl<T: CanSort> CustomSort for Vec<T> {
23 fn do_sort(&mut self) {
24 self.sort();
25 }
26 }
27 // For f64
28 impl CustomSort for Vec<f64> { // Do we need to change this to implement f64 instead of Vec<f64>?
29 fn do_sort(&mut self) {
30 self.sort_by(f64::total_cmp);
31 }
32 }
33 // For f32
34 impl CustomSort for Vec<f32> {
35 fn do_sort(&mut self) {
36 self.sort_by(f32::total_cmp);
37 }
38 }
39
This code does what i want it to: I can create a: Vec<f64> = vec!([2.2, 3.3, 1.1])
and run a.do_sort()
and it works as expected. I can also use this function directly as a library:
use crate::customsort::{CustomSort};
pub mod customsort;
fn main() {
let list_f64: [f64; 3] = [2.2, 3.3, 1.1];
let mut f64v: Vec<f64> = Vec::from(list_f64);
let list_i64: [i64; 3] = [2, 3, 1];
let mut i64v: Vec<i64> = Vec::from(list_i64);
f64v.do_sort();
i64v.do_sort();
assert_eq!(f64v, Vec::from([1.1_f64, 2.2, 3.3]));
assert_eq!(i64v, Vec::from([1_i64, 2, 3]));
}
But I would like to be able to use .do_sort()
within a function. This is where I encounter a lot of problems:
use crate::customsort::{CustomSort, CanSort};
pub mod customsort;
fn main() {
let mut f64v: Vec<f64> = Vec::from([2.2, 3.3, 1.1]);
test_do_sort(&mut f64v);
}
fn test_do_sort<T>(v: &mut Vec<T>)
where
T: CustomSort + CanSort + Copy + Ord + std::fmt::Debug
{
v.do_sort();
}
with cargo run
this produces the error:
error[E0277]: the trait bound `f64: CustomSort` is not satisfied
--> src/main.rs:77:18
|
77 | test_do_sort(&mut f64v);
| ------------ ^^^^^^^^^ the trait `CustomSort` is not implemented for `f64`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `CustomSort`:
Vec<T>
Vec<f32>
Vec<f64>
note: required by a bound in `test_do_sort`
--> src/main.rs:82:8
|
80 | fn test_do_sort<T>(v: &mut Vec<T>)
| ------------ required by a bound in this function
81 | where
82 | T: CustomSort + CanSort + Copy + Ord + std::fmt::Debug
| ^^^^^^^^^^ required by this bound in `test_do_sort`
error[E0277]: the trait bound `f64: CanSort` is not satisfied
--> src/main.rs:77:18
|
77 | test_do_sort(&mut f64v);
| ------------ ^^^^^^^^^ the trait `CanSort` is not implemented for `f64`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `CanSort`:
i32
i64
u32
u64
note: required by a bound in `test_do_sort`
--> src/main.rs:82:21
|
80 | fn test_do_sort<T>(v: &mut Vec<T>)
| ------------ required by a bound in this function
81 | where
82 | T: CustomSort + CanSort + Copy + Ord + std::fmt::Debug
| ^^^^^^^ required by this bound in `test_do_sort`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `common_collections_samples` (bin "common_collections_samples") due to 2 previous errors
While I understand that Rust complains that I'm trying to create a function which accepts Types which have both traits CustomSort
and CanSort
, which have no overlap, I'm struggling to figure out a way to allow all Types that have either of these traits, as both provide an implementation for do_sort()
for the different Types. I can't add f32
or f64
to CanSort
, as these are not members of trait Ord
and can't be sorted with the typical .sort()
.
I've been stuck on this for more than a day, and would be very happy for any help or pointers to a better way of achieving the same goal (without relying on a separate Crate, since I want to understand better how to do this myself, not just get a finished implementation of .sort()
).
Many thanks
// André