pub trait Skip<I: Iterator> {
fn skip(&mut self, steps: usize);
}
impl<I: Iterator> Skip<I> for I {
fn skip(&mut self, mut steps: usize) {
for _ in self {
steps -= 1;
if steps <= 0 {
break;
}
}
}
}
fn main() {
let s = "abc123def";
let mut chars = s.chars();
chars.skip(2);
println!("{:?}", chars.collect::<String>());
}
错误:
error: use of moved value: `chars` [--explain E0382]
--> <anon>:20:22
19 |> chars.skip(2);
|> ----- value moved here
20 |> println!("{:?}", chars.collect::<String>());
|> ^^^^^ value used here after move
<anon>:20:22: 20:27: note: in this expansion of format_args!
<anon>:20:22: 20:27: note: in this expansion of print! (defined in <std macros>)
<anon>:20:22: 20:27: note: in this expansion of println! (defined in <std macros>)
note: move occurs because `chars` has type `std::str::Chars<'_>`, which does not implement the `Copy` trait
error: aborting due to previous error
playpen: application terminated with error code 101
答案 0 :(得分:4)
可以通过采用可变参考来移动值吗?
没有。引用不会移动引用的项目。这是一个很大的参考点。
但是,Iterator::skip
确实取得了迭代器的所有权,这是一个移动:
fn skip(self, n: usize) -> Skip<Self>
要解决错误,您可以......采取可变参考!
chars.by_ref().skip(2);
但是,请注意,调用迭代器适配器而不使用它不执行任何操作:
警告:必须使用的未使用结果:迭代器适配器是惰性的,除非消耗
否则不执行任何操作
这里的真正的问题是你没有调用你认为自己的skip
。如果您将方法重命名为skip2
,则会看到它按预期工作。
这是因为方法查找更喜欢在by-mutable-reference(self
)之前接受by-reference(&self
)之前的接收器by-value(&mut self
)的方法。 / p>
选择与标准库相同的方法名称可能是一个坏主意,特别是对于迭代器,但是非常令人惊讶的是没有打印警告说有多种适用的方法在范围内。
您可以使用Universal Function Call Syntax (UFCS)来指定要调用的实现:
pub trait Skip: Iterator {
fn skip(&mut self, steps: usize) {
for _ in self.take(steps) {}
}
}
impl<I> Skip for I where I: Iterator {}
fn main() {
let s = "abc123def";
let mut chars = s.chars();
Skip::skip(&mut chars, 2);
println!("{:?}", chars.collect::<String>());
}