可迭代对象,.iter(&mut self) 和从不可变数据中借用可变引用。

4
fn main() {
    let x = &vec![1,2,3,5,7,11,13,17,19,23,29,31,37,41,47];
    let mut i = x.iter().map(|x|{2*x});

    while let Some(value) = i.next() {
        println!("{}", value);
    }
}

为什么这样可以工作?

如果我将let mut i = 改为 let i =,就会出现错误:

  |
3 |     let i = x.iter().map(|x|{2*x});
  |         - help: consider changing this to be mutable: `mut i`
4 | 
5 |     while let Some(value) = i.next() {
  |                             ^^^^^^^^ cannot borrow as mutable

问题:

  1. 我真的需要borrow as mutable吗?(也许我错过了什么。)
  2. 为什么我需要borrow as mutable?
  3. 这里实际上是可变的是什么?是i(可迭代对象)还是value(它的值)?
2个回答

2

迭代器i必须是可变的,因为它有内部状态,在调用next时更新。这就是Iterator trait的工作方式。

你可以看到,Iterator::nextself进行了可变借用。

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

2
在Rust中,迭代器是有状态的。 .next 会就地修改它以获取下一个值。即使底层数据结构是不可变的,迭代器基本上也是一个被美化的指针,并且是可变的。不可变的迭代器几乎没有用处:因为它不能在数据结构中移动,所以它总是访问相同的元素。
注意,如果您只是将所有权传递给其他内容,则不需要可变迭代器。因此,最初的 x.iter() 不需要明确存储在可变位置中,因为它的所有权立即传递给了 .map。另一方面,.map 迭代器由您的函数修改,因此需要存储在标记为可变的变量中。
  1. 我真的需要借用为可变吗? (也许我漏掉了什么。)

是的,您的代码是正确的。虽然 for value in i 更符合惯用法。

  1. 为什么我需要借用为可变?

由于迭代器在数据上移动(有状态),因此需要能够更改自己的本地状态以更改其指向的元素。

  1. 这里真正可变的是什么?是 i(可迭代对象)还是 value(它的值)?

迭代器 i 是可变的。可迭代对象是 x,在您的示例中它不可迭代。

另请参见我在类似问题上的答案,其中解释了相同的概念。


1
实际上,for value in i 不需要 i 是可变的,因为它被移入了循环中(playground)。 - Jmb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接