如何在Rust中一次使用Vec中的多个项目?

tro*_*nje 6 rust

我一直在与借阅检查员打架......我想要做的就是:

#[derive(Debug)]
struct SomeStruct {
    value: String,
}

impl SomeStruct {
    fn new(value: &str) -> SomeStruct {
        SomeStruct { value: value.to_string() }
    }

    fn change_value(&mut self, new_value: &str) {
        self.value = new_value.to_string();
    }
}

fn main() {
    let mut my_vec = vec![
        SomeStruct::new("foo"),
        SomeStruct::new("bar"),
    ];

    my_vec[0].change_value(my_vec[1].value.as_str());
}
Run Code Online (Sandbox Code Playgroud)

这是我遇到的问题的一个非常通用的版本.这是stderr:

error[E0502]: cannot borrow `my_vec` as immutable because it is also borrowed as mutable
  --> src/main.rs:22:30
   |
22 |     my_vec[0].change_value(my_vec[1].value.as_str());
   |     ------                 ^^^^^^                  - mutable borrow ends here
   |     |                      |
   |     |                      immutable borrow occurs here
   |     mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)

所以借用检查器不允许我借两次向量(一次是可变的,然后又是不可变的),这是我理解的.但令人沮丧的是,我想修改向量中的一个元素,而只读取另一个元素.我是Rust的新手(惊喜!),我不确定我是否已经把我的想法全部包含在所有细节和设计选择中.但这是感觉它应该工作的东西,但却没有.我错过了什么,我能做些什么来使这个(或类似的行为)起作用?任何帮助是极大的赞赏!

Luk*_*odt 6

我同意,这有点令人困惑.让我们首先看一下,为什么Rust编译器不允许这样做.

为什么不允许这样做

索引运算符[]可以重载,这意味着该语言的用户可以指定它的工作方式.Rust尝试最小化编译器具有某些特殊知识的类型的数量.因此,尽管它很受欢迎,但它Vec<T>只是一个由图书馆定义的普通类型.你可以编写自己的,Vec<T>而不告诉编译器!

Vec<T>还重载索引运算符,以允许索引向量.但由于重载可以做任何事情,它总是可以返回向量的第一个元素!如果你假设索引操作符会做这么奇怪的事情,那么不应该允许这段代码:

my_vec[0].change_value(my_vec[1].value.as_str());
Run Code Online (Sandbox Code Playgroud)

因为my_vec[0]my_vec[1]引用相同的值.

如何使它工作

当然,索引运算符并没有以这种愚蠢的方式实现,我们知道这一点.为了获得对向量的不同元素的两个引用(其中至少一个是可变的),我们必须使用一些特殊函数而不是索引运算符.并且有很多方法可以做到:

我无法告诉你使用什么方法,因为我不知道你的确切用例.但只是为了修复你的例子,你可以写:

let (head, tail) = my_vec.split_first_mut();
head.change_value(tail[0].value.as_str());
Run Code Online (Sandbox Code Playgroud)