Return 对象条目的可变实例

Return mutable instance of entry of an object

我想了解是否允许在 Rust 中获取对结构内部向量条目的可变引用。

我在结构中有一个向量,我想return对其索引字段之一的引用。

示例代码:


#[derive(Debug)]
pub struct Definition {
    v1: Vec<(String, i32)>,
}

impl Definition {
    fn new() -> Self {
        Self {
            v1: Vec::new(),
        }
    }

    fn insert_some_values(&mut self) {
        self.v1.push(("V1".to_string(), 0));
        self.v1.push(("V2".to_string(), 1));
        self.v1.push(("V3".to_string(), 2));
        self.v1.push(("V4".to_string(), 3));
    }

    fn search(&mut self, st: String) -> Result<&mut (String, i32), u32> {
        for i in &self.v1 {
            if st.eq(&i.0) {
                return Ok(I); // Is this supported in someway?
            }
        }
        return Err(0);
    }
}

fn main() {
    let mut def = Definition::new();
    def.insert_some_values();
    let res = def.search("V2".to_string());
    println!("{:?}", res);
}

很明显,只在编译时出错:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:23:27
   |
23 |                 return Ok(i);
   |                           ^ types differ in mutability
   |
   = note: expected mutable reference `&mut (String, i32)`
                      found reference `&(String, i32)`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

但是我想知道有没有什么办法可以支持?

很可能,它不受支持,因为通过这种方式,它实质上是将字段的部分所有权丢失给调用者,这是不允许的。也许只允许对结构中的各个项目拥有部分所有权,但不允许在对象内拥有。

但是如果支持的话,有人可以帮忙吗?

谢谢!

Playground

您尝试做的很好 — 您只是错过了一点:

    fn search(&mut self, st: String) -> Result<&mut (String, i32), u32> {
        for i in &mut self.v1 {   // HERE
            if st.eq(&i.0) {
                return Ok(i);
            }
        }
        return Err(0);
    }

循环必须写成for i in &mut self.v1(或者,等效地,for i in self.v1.iter_mut(),这样你迭代的is是&mut引用,而不是& 引用。通过此更改,您的代码将编译并 运行.


一些补充建议:

  • 不要使用不必要的 returns。
  • 使用 == 代替 .eq()
  • 不要 return 不传达任何信息的错误值 — 而是使用 Option
  • 使用 &str 而不是 String,这样调用者就没有义务传递随后将被释放的字符串。
    fn search(&mut self, st: &str) -> Option<&mut (String, i32)> {
        for i in self.v1.iter_mut() {
            if i.0.as_str() == st {
                return Some(i);
            }
        }
        None
    }

如果愿意,您也可以单独使用迭代器方法编写函数。这与循环相同,但可能更方便 and/or 可读 - 在这种情况下不一定,但在稍微复杂的情况下:

    fn search(&mut self, st: &str) -> Option<&mut (String, i32)> {
        self.v1.iter_mut().filter(|i| i.0.as_str() == st).next()
    }