Home > Back-end >  In Rust, how do I combine two functions that are identical, but one takes &Vec<String> and the
In Rust, how do I combine two functions that are identical, but one takes &Vec<String> and the

Time:12-24

I've been doing the Advent of Code to learn Rust, and on day 3 I ended up writing this:

fn ones_per_bit(lines:&Vec<String>, bitcount:usize) -> Vec<u32> {
  let mut out: Vec<u32> = Vec::new();
  out.resize(bitcount, 0);
  for line in lines {
    for (i, c) in line.chars().enumerate() {
      if c == '1' { out[i]  = 1; }
    }
  }
  return out;
}

And then copied/pasted it so that I can call it with a &Vec<&String> instead of a &Vec<String>. This worked, but to avoid duplicating the function body, I was hoping to use generics, but my naive implementation looked like this:

fn ones_per_bit<T>(lines:&Vec<T>, bitcount:usize) -> Vec<u32> {
  let mut out: Vec<u32> = Vec::new();
  out.resize(bitcount, 0);
  for line in lines {
    for (i, c) in line.chars().enumerate() {
      if c == '1' { out[i]  = 1; }
    }
  }
  return out;
}

Which resulted in:

error[E0599]: no method named `chars` found for reference `&T` in the current scope
  --> main.rs:44:24
   |
44 |     for (i, c) in line.chars().enumerate() {
   |                        ^^^^^ method not found in `&T`

So I'm missing a concept here. I seem to need to tell rust what types of methods to expect on the generic type, but I'm not sure the best way to do that (or if there's a better language feature I should be using here).

CodePudding user response:

What you want here is a type that you can dereference as &str.

This is usually done with a <T: AsRef<str>> generic constraint:

fn ones_per_bit<T: AsRef<str>>(lines: &[T], bitcount:usize) -> Vec<u32> {
  let mut out: Vec<u32> = Vec::new();
  out.resize(bitcount, 0);
  for line in lines {
    for (i, c) in line.as_ref().chars().enumerate() {
      if c == '1' { out[i]  = 1; }
    }
  }
  return out;
}

Side note: declare the argument as &[T] rather than &Vec[T] so that it works for bot vec references and slices thanks to deref coercion. See Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?

  • Related