Generics implementation of traits with max code reusage

Hi,
this is more of a style question. What I want to achieve is to have a generic definition of a trait and implement it for different types but in some cases the underlying function is exactly the same in implementation and I see no reason to repeat my code. So my question is: Is there a way to maximize code reuse ? Example of what I have :slight_smile:

pub type A<T> = Vec<T>;

pub trait AA <T> {
    fn init(i: T)-> A<T>;
}


impl AA<i32> for A<i32>{
    fn init(i: i32)-> A<i32>{
        let mut aa : A<i32> = Vec::new();
        for x in 1..i as usize {
            aa.push(x as i32);
        }
        aa
    }
}

impl AA<i64> for A<i64>{
    fn init(i: i64)-> A<i64>{
        let mut aa : A<i64> = Vec::new();
        for x in 1..i as usize {
            aa.push(x as i64);
        }
        aa
    }
}

fn main (){
    let x = A::init(10 as i64);
    println!("{:?}", x)
}

And how I would like it to look like:

pub type A<T> = Vec<T>;

pub trait AA <T> {
    fn init(i: T)-> A<T>;
}


impl AA<T> for A<T>{
    fn init(i: T)-> A<T>{
        let mut aa : A<T> = Vec::new();
        for x in 1..i as usize {
            aa.push(x as T);
        }
        aa
    }
}

fn main (){
    let x = A::init(10 as i64);
    println!("{:?}", x)
}

Is there a way to somehow achieve this ? (keep in mind that if I have a chr = T or a string = T, I need to redefine the function explicitly because then I might not be able to utilize the same computation strategy, however in case i32, i64 to which I wish to limit my T the utilization is exactly the same and here I would like to reuse the code )

Thank you !!

You will either have to use an extra trait that knows how to convert an usize into a T or use a macro to generate several impl blocks.

1 Like

Casting to and from usize in your example is unnecessary as Range is an Iterator for all of the integer types. The bound you want for this example is specifically Range<T>: IntoIterator<Item = T>.
You also need a trait to give you the starting index, for which you can use num::One.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=68d51faf5f1c81bbf0c1799aee5d6405

1 Like

just a quick followup (the answer to my original question is legit) but how would one treat the following example if it is not a simple iteration and how would that affect the execution speed:


pub type A<T> = Vec<T>;

pub trait AA <T> {
    fn init(i: T)-> A<T>;
}


impl<T> AA<T> for A<T>
where
    T: One,
{
    fn init(i: T)-> A<T>{
        let mut aa : A<T> = Vec::new();
        while i*2+1 < i*i {
            aa.push(i+7);
        }
        aa
    }
}

fn main (){
    let x = A::init(10i32);
    println!("{:?}", x)
}