我想把下面的Padded
类型变成一个迭代器Transformer:
enum Step<T> {
Before(T),
During(T),
After
}
struct Padded<T> {
step: Step<T>
}
(请注意,在我的实际代码中,Padded
中除了Step
之外还有其他东西,因此从struct
到enum
有额外的间接层.)
我们的 idea 是,在每次迭代中,我们总是更改我们的Step
,因此将存储在其中的T
移到下一个Step
‘S构造函数中应该是合理的.然而,我不能让它工作.
简单的版本:
impl<T: Iterator> Iterator for Padded<T> {
type Item = Option<T::Item>;
fn next(&mut self) -> Option<Self::Item> {
match &self.step {
Step::Before(start) => {
self.step = Step::During(*start);
Some(None)
},
Step::During(ref mut iter) => {
match iter.next() {
Some(x) => { self.step = Step::During(*iter); Some(Some(x)) },
None => { self.step = Step::After; Some(None) },
}
},
Step::After => {
None
}
}
}
}
由于以下原因,此操作失败:
error[E0507]: cannot move out of `*start` which is behind a shared reference
--> src/lcd.rs:39:42
|
39 | self.step = Step::During(*start);
| ^^^^^^ move occurs because `*start` has type `T`, which does not implement the `Copy` trait
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/lcd.rs:42:26
|
42 | Step::During(ref mut iter) => {
| ^^^^^^^^^^^^ cannot borrow as mutable
error[E0507]: cannot move out of `*iter` which is behind a mutable reference
--> src/lcd.rs:44:59
|
44 | Some(x) => { self.step = Step::During(*iter); Some(Some(x)) },
| ^^^^^ move occurs because `*iter` has type `T`, which does not implement the `Copy` trait
我试着通过将第三个分支改为:
Step::After => {
self.step = Step::After;
None
}
但这并不能改变任何事情.
然后我想我应该更清楚地说明这里发生了什么:
impl<T: Iterator> Padded<T> {
fn next_self_and_item(self) -> (Self, Option<Option<T::Item>>) {
match self.step {
Step::Before(start) => {
(Padded{ step: Step::During(start) }, Some(None))
},
Step::During(mut iter) => {
match iter.next() {
Some(x) => (Padded{ step: Step::During(iter) }, Some(Some(x))),
None => (Padded{ step: Step::After }, Some(None)),
}
},
Step::After => {
(Padded{ step: Step::After }, None)
}
}
}
}
此函数确实通过了borrow 判断器,但不能用于实现Iterator::next
:
impl<T: Iterator> Iterator for Padded<T> {
type Item = Option<T::Item>;
fn next(&mut self) -> Option<Self::Item> {
let (new_self, item) = self.next_self_and_item();
*self = new_self;
item
}
}
error[E0507]: cannot move out of `*self` which is behind a mutable reference
--> src/lcd.rs:79:32
|
79 | let (new_self, item) = self.next_self_and_item();
| ^^^^ -------------------- `*self` moved due to this method call
| |
| move occurs because `*self` has type `Padded<T>`, which does not implement the `Copy` trait
|
note: `Padded::<T>::next_self_and_item` takes ownership of the receiver `self`, which moves `*self`
--> src/lcd.rs:57:27
|
57 | fn next_self_and_item(self) -> (Self, Option<Option<T::Item>>) {
| ^^^^
那么我能做些什么呢?另外,我认为至少在道德上,我试图做的应该是好的,因为self
是一个可变的引用(所以我应该能够做我想做的任何事情),并且在所有分支中,self.step
内部的T
只是被移动?