Reputation: 151
I want to get a function to accept two Iterator
s and a callback and process as follows:
fn for_xy<I: Iterator<Item = usize>, F>(ix: I, iy: I, f: F)
where
I: Iterator<Item = usize>,
F: FnMut(usize, usize) -> (),
{
for x in ix {
for y in iy {
f(x, y);
}
}
}
but I get this error:
error[E0382]: use of moved value: `iy`
--> src/lib.rs:7:18
|
1 | fn for_xy<I: Iterator<Item = usize>, F>(ix: I, iy: I, f: F)
| -- move occurs because `iy` has type `I`, which does not implement the `Copy` trait
...
7 | for y in iy {
| ^^ `iy` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
|
note: this function takes ownership of the receiver `self`, which moves `iy`
help: consider borrowing to avoid moving into the for loop
|
7 | for y in &iy {
| ^^^
help: consider further restricting this bound
|
3 | I: Iterator<Item = usize> + Copy,
| ^^^^^^
How can I correct this program?
Upvotes: 4
Views: 1813
Reputation: 3344
When you run a for
loop, the iterable argument you pass is moved into the for
loop; after iteration completes, the iterator is dropped. If you want to make the iterator reusable, the typical way is to add a Clone
bound. Additionally, in principle you're going to have the same problem (in reverse) with you x
items from the ix
iterator: because you're reusing them with each iteration of the iy
loop, you need to ensure they can be cloned or copied. This problem doesn't happen with usize
, which is copyable, but a more generic version will need to include a Clone
or Copy
bound on ix::Item
:
fn for_xy<X, Y, F>(ix: X, iy: Y, f: F)
where
X: Iterator,
X::Item: Clone,
Y: Iterator + Clone,
F: FnMut(X::Item, Y::Item)
) -> {
for x in ix {
for y in iy.clone() {
f(x.clone(), y)
}
}
}
In practice, most iterators you encounter in Rust are cheaply cloneable. The colletion iterators (such as Vec::iter
, HashMap::iter
) contain simple references to the underlying collection, and most iterator adapters (map
, filter
, etc) are cheaply cloneable so long as the iterator being adapted is as well.
Upvotes: 3