I have a for loop where the first iteration is a special case. The only difference is the type of one variable even though they both implement the same traits. I want to know if and how I can make it more concise.
There is a concrete type called Concrete. It implements a trait FooTrait<T> with method foo<T>(&mut self, modifier: T) for various Ts. Notably, FooTrait<&Concrete> is implemented.
I have a function bar() that looks something like this:
pub fn bar(slice_len, initial: &Concrete) {
let concrete_slice[Concrete; slice_len] = initialize_slice();
let mut carry: &Concrete = initial;
for i in 0..concrete_slice.len() {
concrete_slice[i].foo(carry);
carry = &concrete_slice;
}
epilogue(carry);
}
I want to allow it to take different types of initial values by using generics. (note: the function must be able to accept anonymous types because some of the types are private in a separate crate.)
pub fn bar<T>(slice_len, initial: T)
where
Concrete: FooTrait<T>
{
let concrete_slice[Concrete; slice_len] = initialize_slice();
if slice_len > 0 {
concrete_slice[0].foo(initial);
let mut carry: &Concrete = &concrete_slice[0];
for i in 1..concrete_slice.len() {
concrete_slice[i].foo(carry);
carry = &concrete_slice[i];
}
epilogue(carry);
} else {
epilogue(initial);
}
}
Obviously, this is a generalized and simplified example, and my actual code is more complex. I would rather it look closer to the first one than the second one for readability.
I know if I want to make a wrapper around multiple different types I can use enum. However, if there is a way to use enums without making the code less concise, I don't know about it. I also know trait objects are a thing, but those have runtime costs. Is there a better idiom for this?