编写迭代器

Chu*_*uck 5 iterator rust

编者注:此代码示例来自1.0之前的Rust版本,并且不是有效的Rust 1.0代码.由于更改了for循环的实现方式,此代码的更新版本不再产生错误.

我正在Rust中编写一个Vector结构.

pub struct Vector {
    pub x: f32,
    pub y: f32,
    pub z: f32,

    curr: uint
}
Run Code Online (Sandbox Code Playgroud)

我想为它编写一个简单的迭代器,以便我可以迭代向量的元素.它偶尔会有用,而且我对Rust中的迭代器几乎一无所知.

这就是我现在所拥有的.

impl Iterator<f32> for Vector {
    fn next(&mut self) -> Option<f32> {
        let new_next : Option<f32> = match self.curr {
            0 => Some(self.x),
            1 => Some(self.y),
            2 => Some(self.z), 
            _ => None
        };
        let new_curr = (self.curr + 1) % 4;
        mem::replace(&mut self.curr, new_curr);
        new_next
    }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望能够像以下一样使用它:

let u = Vector::new(0.0f32, 0.0f32, 0.0f32);
for element in u {
    ///
}
Run Code Online (Sandbox Code Playgroud)

但是,我得到以下编译器错误:

 error: cannot borrow immutable local variable `u` as mutable
Run Code Online (Sandbox Code Playgroud)

所以我很难过.经过几个小时的谷歌搜索,我无法想出任何东西.我觉得我错过了一些巨大的东西.

Vla*_*eev 15

你确定你真的希望Vector 自己成为一个迭代器吗?通常,结构和迭代器是分开的.考虑这样的事情:

pub struct Vector {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

pub struct VectorIter<'a> {
    vector: &'a Vector,
    cur: usize,
}

impl<'a> Iterator for VectorIter<'a> {
    type Item = f32;

    fn next(&mut self) -> Option<f32> {
        let r = match self.cur {
            0 => self.vector.x,
            1 => self.vector.y,
            2 => self.vector.z,
            _ => return None,
        };
        self.cur += 1;
        Some(r)
    }
}

impl Vector {
    fn iter(&self) -> VectorIter {
        VectorIter {
            vector: self,
            cur: 0,
        }
    }
}

fn main() {
    let v = Vector { x: 1.0, y: 2.0, z: 3.0 };
    for c in v.iter() {
        println!("{}", c);
    }
}
Run Code Online (Sandbox Code Playgroud)

因为Vector它非常简单,它可以派生Copy,并且它的迭代器可以通过值来获取它:

#[derive(Copy, Clone)]
pub struct Vector {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

pub struct VectorIter {
    vector: Vector,
    cur: usize,
}

impl Iterator for VectorIter {
    type Item = f32;
    fn next(&mut self) -> Option<f32> {
        let r = match self.cur {
            0 => self.vector.x,
            1 => self.vector.y,
            2 => self.vector.z,
            _ => return None,
        };
        self.cur += 1;
        Some(r)
    }
}

impl Vector {
    fn iter(&self) -> VectorIter {
        VectorIter {
            vector: *self,
            cur: 0,
        }
    }
}

fn main() {
    let v = Vector { x: 1.0, y: 2.0, z: 3.0 };
    for c in v.iter() {
        println!("{}", c);
    }
}
Run Code Online (Sandbox Code Playgroud)

除非您Vector包含除坐标之外的其他内容,否则此变体可能更好.这个变体更灵活,因为它没有将迭代器与迭代器绑定,但另一方面,正是由于同样的原因,它可能是不可取的(Copy你可以改变原始值,迭代器不会反映它;没有Copy和有参考,你将无法改变原始值.您希望大量使用的语义取决于您的用例.