据我所知,我不应该有一个可变的引用到一个不可变的数据片段.因此,如果我想创建一些struct,它基于内部状态的变化实现Iterator,那么我必须将该struct的任何实例声明为可变的,以便能够创建所需的可变引用.

为了进行演示,我构造了一个简单的示例,如下所示:

struct MyIter {
    internal_state: u32
}

impl MyIter {
    fn new() -> MyIter {
        MyIter{ internal_state: 0 }
    }
}

impl Iterator for MyIter {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        self.internal_state += 1;
        Some(self.internal_state)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::iter::zip;

    #[test]
    fn mutable_declaration_no_zip() {
        let mut my_iter = MyIter::new();
        assert_eq!(my_iter.next(), Some(1));
        assert_eq!(my_iter.next(), Some(2));
        assert_eq!(my_iter.next(), Some(3));
    }
}

这段代码编译得很好,并通过了测试,但是如果我将测试函数更改为my_iter的不可变声明,如下所示,则它拒绝使用预期的error[E0596]: cannot borrow 'my_iter' as mutable, as it is not declared as mutable消息进行编译:

#[test]
fn immutable_declartaion_no_zip() {
    let my_iter = MyIter::new();
    assert_eq!(my_iter.next(), Some(1));
    assert_eq!(my_iter.next(), Some(2));
    assert_eq!(my_iter.next(), Some(3));
}

我的问题涉及这样的情况,即我基本上与上面的操作相同,但使用std::iter::zip来执行迭代.现在发生的情况是,即使我声明my_iter是不可变的,测试还是编译并通过了,这意味着在幕后zip已经改变了我传递给它的不可变变量的状态!

#[test]
fn immutable_declaration_zip() {
    let my_iter = MyIter::new();
    let nums: [u32;10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    for (i, num) in zip(my_iter, nums.iter()) {
        assert_eq!(i, *num);
    }
}

那么,有没有人能解释一下为什么要设立zip来做这件事?zip如何调用next()方法,从而生成对我已声明为不可变的数据的可变引用?

推荐答案

可变性注释(mut或没有)跟随变量,而不是值.

let mut my_iter = MyIter::new();

在这里,不是my_itervalue是可变的.它本身就是my_iter.只要my_iter拥有这个值,它就是可变的.所以你可以调用my_iter.next(),这需要一个可变的引用.

let my_iter = MyIter::new();

同样的论点,但没有mut.只要my_iter拥有迭代器,它就是immutable,所以不允许对它进行可变引用.

However,这里的关键短语是"只要my_iter拥有迭代器".

zip(my_iter, nums.iter())

std::iter::zipsignature

pub fn zip<A, B>(
    a: A,
    b: B
) -> Zip<<A as IntoIterator>::IntoIter, <B as IntoIterator>::IntoIter>
where
    A: IntoIterator,
    B: IntoIterator,

它把两个论点都接受了value次.当你呼叫zip的那一刻,该函数就取得了值的所有权.这意味着nobody当前有一个对值的引用(可变或不可变),zip可以自由决定它是否是可变的,因为它现在是独占所有者.

Rust相关问答推荐

基于对vec值的引用从该值中删除该值

如何从接收&;self的方法克隆RC

访问Rust中的隐藏变量

使用 struct 外部的属性来改变 struct 的原始方式

将数组转换为HashMap的更简单方法

默认特征实现中的生命周期问题

无法从流中读取Redis请求

带参考文献的 rust 元组解构

对reqwest提供的这种嵌套JSON struct 进行反序列化

这是什么:`impl Trait for T {}`?

使用占位符获取用户输入

Rust中的一生语法有什么作用?

为什么不能在 Rust 中声明静态或常量 std::path::Path 对象?

Rust 中的生命周期:borrow 的 mut 数据

从 HashMap>, _> 中删除的生命周期问题

在 Rust 中,我如何处理请求 javascript 的页面?

如何使返回 XMLError 的方法与 anyhow::Error 兼容?

当我在 struct 中存储异步函数时,为什么它需要生命周期

为什么我可以在没有生命周期问题的情况下内联调用 iter 和 collect?

如何构建包含本地依赖项的 docker 镜像?