I am trying to build a function similar to np.zeros from Python for Rust.
I would like to do something like:
trait VectorHelper {
fn fill_with<A>(&mut self, value: A) -> &mut Self;
}
impl<T: VectorHelper> VectorHelper for Vec<T> {
fn fill_with<A>(&mut self, value: A) -> &mut Self {
for elem in self.iter() {
if elem.is_vec() {
elem.fill_with(value);
} else {
*elem = value;
}
}
self
}
}
But I do not know how to get this to work, because there is no general conversion for A to T. What can I do to make the compiler accept this assignment: "*elem = value"?
While the exact implementation like you want it isn't possible you can still handle all the additional layers but the first by a blanket implementation:
impl<V: Clone, T: VectorHelper<V>> VectorHelper<V> for Vec<T> {
fn fill_with(&mut self, value: V) -> &mut Self {
for elem in &mut *self {
elem.fill_with(value.clone());
}
self
}
}
Then for each base type you can implement the trait once (possibly by a macro to reduce duplication):
macro_rules! impl_vector_helper {
($t:ty) => {
impl VectorHelper<$t> for Vec<$t> {
fn fill_with(&mut self, value: $t) -> &mut Self {
self.fill(value);
self
}
}
};
($($t:ty),* $(,)?) => {
$(impl_vector_helper!{$t})*
};
}
impl_vector_helper! {
u8, u16, u32, u64,
i8, i16, i32, i64,
f32, f64,
&'static str,
}
You just have to move the generic from the function to the trait:
trait VectorHelper<V> {
fn fill_with(&mut self, value: V) -> &mut Self;
}