在不可变迭代器上运行 next 时不能作为可变借用(没有其他借用)

ste*_*kwr 4 rust

当尝试运行以下代码时:

fn main() {
    let s1 = String::from("hello world");
    println!("The first word in the string is: {}", return_first_word(&s1));
}

fn return_first_word(s: &String) -> String {
    let t = s.split(" ");
    String::from(t.next().unwrap())
}
Run Code Online (Sandbox Code Playgroud)

我收到错误cannot borrow as mutable消息String::from(t.next().unwrap())。当然,当我let t = ...用以下内容替换该行时let mut t = ...代码替换该行时效果很好。

我的问题是,有人可以解释为什么吗?这里借了什么,借了什么?我检查了新创建的不可变变量的类型t,它是一个迭代器。为什么迭代迭代器会出现问题?

Sil*_*olo 10

如果您熟悉 Java 这样的语言,您可能期望str::split返回一个数组,但实际上并没有。在 Rust 中,str::split返回一个迭代器。它实际上并没有立即分割整个字符串;它为您提供了一个特殊的迭代器对象,该对象您迭代字符串时执行此操作。

现在,迭代是 Rust 中的一个有状态的过程。要迭代某些内容,您可以调用Iterator::next,这会更改迭代器的内部状态并生成下一个值。如果重复调用,它会按顺序给出迭代器的每个值,然后开始生成None。由于next更改了迭代器的状态,因此它必须具有对迭代器的可变引用。

当你在 Rust 中声明一个变量时let,它是不可变的。你无法改变它。你已经告诉 Rust 系统你无意改变它。因此,当您尝试对您承诺永远不会更改的事物(在您的情况下是迭代器)进行可变引用时,Rust 会抱怨。相反,您需要使用let mut来表明您的意图。

  • 当所有权易手时,值的可变性可能会发生变化。因此,举例来说,如果您获得一个迭代器,将其存储在变量中,然后将其所有权传递给其他函数,即使您存储它的变量是“let”(即不可变),您给它的函数可以选择变异它。迭代器本身并不是不可变的,只是当时恰好拥有它的变量而已。 (2认同)