为什么Iterator :: all需要迭代器是可变的?

Jus*_*ker 2 iterator rust

我在一个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作为论据.

我的参考map/ filter/all.

在这件事上看到了一个问题,但没有给出任何解释.

She*_*ter 5

迭代任何东西都需要改变迭代器,因为Iterator::next需要&mut self.检查迭代器中的所有值需要迭代,因此Iterator::all(以及许多类似的方法)也需要迭代&mut self.

all方法不应该改变迭代器.

我很想听听您如何在调用的情况下检查迭代器中的每个值next.

喜欢mapfilter

这些方法返回一个新的迭代器,它们不会调用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签名中都没有.这是因为它对调用者无关紧要.


E_n*_*ate 5

迭代器方法allany采用可变引用,因为它们将通过消耗迭代器的元素来修改迭代器(请注意,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移动。值不必绑定到可变变量才能移动到另一个作用域,即使稍后在该上下文中修改它们也是如此。