在 Rust 中,如何组合两个相同的函数,但一个采用 Vec<String> 而另一个采用 Vec<&String>?

In Rust, how do I combine two functions that are identical, but one takes &Vec<String> and the other takes &Vec<&String>?

我一直在做代码的出现来学习 Rust,在第 3 天我写下了这个:

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

然后是 copied/pasted,这样我就可以用 &Vec<&String> 而不是 &Vec<String> 来调用它。这行得通,但为了避免重复函数体,我希望使用泛型,但我天真的实现看起来像这样:

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

结果是:

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`

所以我在这里漏掉了一个概念。我似乎需要告诉 Rust 在泛型类型上期望什么类型的方法,但我不确定最好的方法(或者如果有更好的语言特性我应该在这里使用)。

您在这里想要的是一种可以取消引用的类型 &str

这通常使用 <T: AsRef<str>> 通用约束来完成:

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

旁注:将参数声明为 &[T] 而不是 &Vec[T] 以便它适用于 bot vec 引用和切片,这要归功于 deref coercion. See