编写迭代器 [英] Writing an iterator

查看:64
本文介绍了编写迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Editor's note: This code example is from a version of Rust prior to 1.0 and is not valid Rust 1.0 code. Updated versions of this code no longer produce an error due to changes how for loops are implemented.

我正在用Rust写一个Vector结构.

I'm writing a Vector struct in Rust.

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

    curr: uint
}

我想为其编写一个简单的迭代器,以便可以迭代向量的元素.它偶尔有用,而且我几乎不了解Rust中的迭代器.

And I'd like to write a simple iterator for it, so that I can iterate over the elements of the vector. It's occasionally useful, plus I know next to nothing about iterators in Rust.

这就是我现在所拥有的.

Here's what I've got at the moment.

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
    }
}

现在理想情况下,我希望能够像这样使用它:

Now ideally I'd like to be able to use this like:

let u = Vector::new(0.0f32, 0.0f32, 0.0f32);
for element in u {
    ///
}

但是,出现以下编译器错误:

However, I get the following compiler error:

 error: cannot borrow immutable local variable `u` as mutable

所以我很困惑.经过两个小时的谷歌搜索,我什么都没想出来.我觉得我想念一些巨大的东西.

So I'm stumped. After a couple hours of Googling, I couldn't come up with anything. I feel like I'm missing something huge.

推荐答案

您确定要真正将Vector 本身用作迭代器吗?通常,结构和迭代器是分开的.考虑这样的事情:

Are you sure you really want the Vector itself to be an iterator? Usually structures and iterators into them are separate. Consider something like this:

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);
    }
}

因为Vector非常简单,它可以派生Copy,并且其迭代器可以按值获取它:

Because Vector is very simple, it can derive Copy, and its iterator can take it by value:

#[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);
    }
}

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

This variant is probably better unless your Vector contains something other than coordinates. This variant is more flexible because it does not tie the iterator with the iterable, but on the other hand, exactly because of the same reason it may be undesirable (with Copy you can change the original value, and the iterator won't reflect it; without Copy and with references you won't be able to change the original value at all). The semantics you would want to use heavily depends on your use cases.

这篇关于编写迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆