当 运行 next 在不可变迭代器上时不能作为可变借用(没有其他借用)
Cannot borrow as mutable when running next on an immutable iterator (no other borrows)
尝试运行以下代码时:
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())
}
我在 String::from(t.next().unwrap())
行收到错误 cannot borrow as mutable
。当然,当我将 let t = ...
行替换为 let mut t = ...
时,代码可以完美运行。
我的问题是,有人可以解释为什么吗?这里借用了什么,借用了什么?我检查了我新创建的不可变变量 t
的类型,它是一个迭代器。为什么迭代迭代器会出现问题?
如果您熟悉 Java 这样的语言,您可能会期望 str::split
到 return 数组,但实际上不是。在 Rust 中,str::split
return 是一个迭代器。它实际上并没有立即拆分整个字符串;它为您提供了一个特殊的迭代器对象,它在 作为 您遍历字符串时执行此操作。
现在,迭代在 Rust 中是一个有状态的过程。要迭代某些内容,您可以调用 Iterator::next
,它会更改迭代器的内部状态并生成下一个值。如果重复调用,它会按顺序为您提供迭代器的每个值,然后开始生成 None
。由于 next
改变了迭代器的状态,它必须有一个指向迭代器的可变引用。
当你在 Rust 中用 let
声明一个变量时,它是不可变的。你无法改变它。您已经告诉 Rust 系统您无意更改它。因此,当您尝试对您承诺永远不会更改的事物(在您的情况下为迭代器)进行可变引用时,Rust 会抱怨。相反,您需要使用 let mut
来表明您的意图。
尝试运行以下代码时:
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())
}
我在 String::from(t.next().unwrap())
行收到错误 cannot borrow as mutable
。当然,当我将 let t = ...
行替换为 let mut t = ...
时,代码可以完美运行。
我的问题是,有人可以解释为什么吗?这里借用了什么,借用了什么?我检查了我新创建的不可变变量 t
的类型,它是一个迭代器。为什么迭代迭代器会出现问题?
如果您熟悉 Java 这样的语言,您可能会期望 str::split
到 return 数组,但实际上不是。在 Rust 中,str::split
return 是一个迭代器。它实际上并没有立即拆分整个字符串;它为您提供了一个特殊的迭代器对象,它在 作为 您遍历字符串时执行此操作。
现在,迭代在 Rust 中是一个有状态的过程。要迭代某些内容,您可以调用 Iterator::next
,它会更改迭代器的内部状态并生成下一个值。如果重复调用,它会按顺序为您提供迭代器的每个值,然后开始生成 None
。由于 next
改变了迭代器的状态,它必须有一个指向迭代器的可变引用。
当你在 Rust 中用 let
声明一个变量时,它是不可变的。你无法改变它。您已经告诉 Rust 系统您无意更改它。因此,当您尝试对您承诺永远不会更改的事物(在您的情况下为迭代器)进行可变引用时,Rust 会抱怨。相反,您需要使用 let mut
来表明您的意图。