Search code examples
rustvector

In Rust I want to assign a given value to all elements of nested vectors


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"?


Solution

  • 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;
    }