Is there any way to optimize this generic type hinting?

I am learning rust for the past few days. I wrote the following code while learning generics.

use std::{
    cmp::{Ordering, PartialOrd},
    convert::Into,
    ops::Mul,
};
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    &largest
}

#[derive(Debug)]
struct Rectangle<T: Mul<Output = T> + Clone + Into<f64>, U: Mul<Output = U> + Clone + Into<f64>> {
    width: T,
    height: U,
}

impl<T: Mul<Output = T> + Clone + Into<f64>, U: Mul<Output = U> + Clone + Into<f64>>
    Rectangle<T, U>
{
    fn area(&self) -> f64 {
        &self.width.clone().into() * &self.height.clone().into()
    }
}

impl<T: Mul<Output = T> + Clone + Into<f64>, U: Mul<Output = U> + Clone + Into<f64>> PartialOrd
    for Rectangle<T, U>
{
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.area().partial_cmp(&other.area())
    }
}
impl<T: Mul<Output = T> + Clone + Into<f64>, U: Mul<Output = U> + Clone + Into<f64>> PartialEq
    for Rectangle<T, U>
{
    fn eq(&self, other: &Self) -> bool {
        self.area() == other.area()
    }
}

pub fn main() {
    let num_list = vec![1, 10, 30, 12, 4];
    println!("The largest int is {}", largest(&num_list));

    let char_list = vec!['y', 'm', 'a', 'q'];
    let result = largest(&char_list);
    println!("The largest char is {}", result);

    let rect_list = vec![
        Rectangle {
            width: 5,
            height: 10.5,
        },
        Rectangle {
            width: 7,
            height: 9.8,
        },
        Rectangle {
            height: 0.5,
            width: 10,
        },
    ];
    let result = largest(&rect_list);
    println!("The largest rectangle is {:?}", result);
}

As you can see, I have had generics hinted like this: <X: Mul<Output = X> + Clone + Into<f64>>. Seems like a lot of duplication. Is there any way I can optimize this?

You could use the Float trait from the num crate instead?

Thanks, but the thing is, I am trying to get it to work with both i32 (or u32) and f64.

If none of the traits in the crate work, then you could write your own trait.

1 Like

Ah okay, I haven't gotten to traits yet. Seems like it is the next chapter in the rust book. Sure, will try doing it.

It is generally not advised to put trait bounds on type definitions directly. Only put generic bounds on impl blocks if possible, and use bounds on structs and enums directly only if required (e.g. if a field needs to store a value of an associated type).

3 Likes

You could start by removing the bounds you aren't really using Rust Playground

If you actually have longer bounds then you can use a helper trait Rust Playground

1 Like

Thank you so much @SkiFire13 . This is exactly what I wanted to learn :smile: you are awesome.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.