编者注:此代码示例来自1.0之前的Rust版本,并且不是有效的Rust 1.0代码。由于更改了
for
循环的实现方式,此代码的更新版本不再产生错误。
我在Rust中编写了一个Vector结构。
pub struct Vector {
pub x: f32,
pub y: f32,
pub z: f32,
curr: uint
}
我想为它编写一个简单的迭代器,以便我可以迭代向量的元素。它偶尔会有用,而且我对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
}
}
现在理想情况下,我希望能够使用它:
let u = Vector::new(0.0f32, 0.0f32, 0.0f32);
for element in u {
///
}
但是,我收到以下编译器错误:
error: cannot borrow immutable local variable `u` as mutable
所以我很难过。经过几个小时的谷歌搜索,我无法想出任何东西。我觉得我错过了一些巨大的东西。
答案 0 :(得分: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);
}
}
因为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);
}
}
除非您的Vector
包含除坐标以外的内容,否则此变体可能更好。这个变体更灵活,因为它没有将迭代器与迭代相关联,但另一方面,正是由于同样的原因,它可能是不可取的(使用Copy
你可以改变原始值,并且迭代器赢了& #39; t反映它;没有Copy
和参考,你根本无法改变原始值。您想要大量使用的语义取决于您的用例。
答案 1 :(得分:4)
编者注:由于
for
循环的工作方式发生了变化,因此Rust 1.0的答案不再有用。
Vladimir Matveev的回答是正确的,并解释了你应该做些什么。我想通过更多地解释你的错误来补充。
错误:无法将不可变局部变量
借用u
作为可变
当你在迭代某些东西时,你需要改变跟踪你所在位置的某些东西。在您的代码中,通过以下方式完成:
mem::replace(&mut self.curr, new_curr);
Rust知道你要改变哪个东西,因为next
的方法签名表明它:
fn next(&mut self) -> Option<f32>
问题是您的对象不可变:
let u = Vector::new(0.0f32, 0.0f32, 0.0f32);
如果您将代码更改为
let mut u = Vector::new(0.0f32, 0.0f32, 0.0f32);
我希望你的代码按原样运行。所有这一切,一个单独的迭代器可能是正确的方法。但是,您对代码的了解比我们更多!