我在一个String
字符上使用了一个迭代器:
pub fn is_yelling(message: &str) -> bool {
let letters = message.chars().filter(|c| c.is_alphabetic());
message.chars().any(|c| c.is_alphabetic()) && letters.all(|c| c.is_uppercase())
}
Run Code Online (Sandbox Code Playgroud)
这会引发编译错误:
error[E0596]: cannot borrow immutable local variable `letters` as mutable
--> src/main.rs:3:51
|
2 | let letters = message.chars().filter(|c| c.is_alphabetic());
| ------- consider changing this to `mut letters`
3 | message.chars().any(|c| c.is_alphabetic()) && letters.all(|c| c.is_uppercase())
| ^^^^^^^ cannot borrow mutably
Run Code Online (Sandbox Code Playgroud)
当我变得letters
可变时,一切都顺利进行.
我不明白为什么这个必要.该all
方法不应该改变迭代器.喜欢map
或者filter
,取self
而不是mut self
作为论据.
迭代任何东西都需要改变迭代器,因为Iterator::next
需要&mut self
.检查迭代器中的所有值需要迭代,因此Iterator::all
(以及许多类似的方法)也需要迭代&mut self
.
该
all
方法不应该改变迭代器.
我很想听听您如何在不调用的情况下检查迭代器中的每个值next
.
喜欢
map
或filter
这些方法返回一个新的迭代器,它们不会调用next
.话虽这么说,他们可以,如果他们想要因为......
采取
self
而不是mut self
作为一个论点.
可变性是变量所有者的属性.这两个功能是等效的:
fn example(mut a: String) {}
Run Code Online (Sandbox Code Playgroud)
fn example(a: String) {
let mut a = a;
}
Run Code Online (Sandbox Code Playgroud)
重要的是,在生成的文档中看起来都是一样的 - mut
签名中都没有.这是因为它对调用者无关紧要.
迭代器方法all
和any
采用可变引用,因为它们将通过消耗迭代器的元素来修改迭代器(请注意,next()
还需要&mut self
,因为它本质上会修改迭代器的状态)。此外,这些方法是短路的,并且不一定消耗迭代器的所有元素。这意味着这些方法可以将迭代器返回给调用者,从而在需要时能够继续使用它。
let x = vec![1, 2, 5];
let mut it = x.into_iter();
assert!(it.any(|x| x > 1));
assert_eq!(it.next(), Some(5));
Run Code Online (Sandbox Code Playgroud)
map
或者filter
工作方式不同,因为它们是迭代器适配器。一旦调用,返回的适配器值将拥有底层迭代器,因此需要self
移动。值不必绑定到可变变量才能移动到另一个作用域,即使稍后在该上下文中修改它们也是如此。