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.
I'm writing a Vector struct in Rust.
pub struct Vector {
pub x: f32,
pub y: f32,
pub z: f32,
curr: uint
}
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.
iterators are not reusable; you need to get a fresh Iterator from the Iterable collection each time you want to iterate over the elements.
Realize that elements could be mutable (or reference dynamic values) and they may reference other structures and semantics which require a customized copy function. Thus copyable iterators is not orthogonal to copyable stream elements, so this is why copyable iterators are not possible in general.
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);
}
}
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);
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With