不能借用“args”作为可变的,因为它也被借用为不可变的

Jon*_*h-H 0 loops rust borrow-checker

let mut args: Vec<String> = args().collect();
for mut i in 0..args.len() {
  if args[i].contains("-type") {
    project_type = args[i].split("=").last().unwrap();
    args.remove(i);
    i-=1;
  }
}
Run Code Online (Sandbox Code Playgroud)

我对 Rust 很陌生,想知道为什么这段代码会给我错误“不能借用‘args’作为可变的,因为它也是借用为不可变的”以及如何修复它

我试图检查 args Vec 是否包含类似“-type=some_type”的项目,然后将“some_type”放入名为“project_type”的变量中。最后我想从列表中删除项目“-type=some_type”并继续搜索。

编辑:如果我正在做我想做错的事情,我将不胜感激更好的解决方案。

Sil*_*olo 5

str::split不创建新的字符串对象,它返回对现有字符串对象的引用。所以你的project_type变量是对 中字符串的引用args。当您remove从 时args,您将使所有这些引用无效。

您可以将 a 转换&str为 aString并使用以下命令中断引用.to_owned()

project_type = args[i].split("=").last().unwrap().to_owned();
Run Code Online (Sandbox Code Playgroud)

现在,forRust 中的循环迭代数据结构。因此,你的i -= 1伎俩不会奏效。i只会重置回下一次迭代时的位置。如果您想按照当前的方式执行此操作,则需要一个while循环。

let mut i = 0
while i < args.len() {
  if ... {
    ...
  } else {
    i += 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

然而,让我们从功能上更深入地考虑一下这个问题。听起来你想要的是找到向量的匹配元素(及其索引),然后用它做一些事情。因此,让我们将其分解为两个单独的问题。

我们用来enumerate获取一个集合及其索引,并find对其进行搜索。因为看起来您期望该值存在,所以我们会它,unwrap如果它不存在,我们会感到恐慌。如果您想处理错误,请将其转换为match.

let (idx, element) = args.iter().find(|x| x.contains("-type")).unwrap();
Run Code Online (Sandbox Code Playgroud)

一旦我们有了它,我们就可以继续工作element以获得项目类型。

project_type = element.split("=").last().unwrap().to_owned();
Run Code Online (Sandbox Code Playgroud)

请注意,此时根本project_type不依赖于。确实如此,Rust 可能足够聪明,能够看到这一点,但我们要绝对安全,并确保在修改. 一旦不再有对 的引用,我们就可以可变地借用来执行操作。argselementelementargsargsremove

let idx = {
  let (idx, element) = args.iter().enumerate().find(|(_, x)| x.contains("-type")).unwrap();
  project_type = element.split("=").last().unwrap().to_owned();
  idx
}
args.remove(idx);
Run Code Online (Sandbox Code Playgroud)