Rust 为什么在这个函数中移动了迭代器?

Rust 为什么在这个函数中移动了迭代器?,rust,iterator,ownership,Rust,Iterator,Ownership,我想得到一个函数,它接受两个迭代器和一个回调,并按如下方式处理: 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);

我想得到一个函数,它接受两个
迭代器和一个回调,并按如下方式处理:

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);
        }
    }
}
fn表示_xy(ix:I,iy:I,f:f)
哪里
I:迭代器,
F:FnMut(usize,usize)->(),
{
对于ix中的x{
在iy中为y{
f(x,y);
}
}
}
但我得到了这个错误:

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,
    |                               ^^^^^^
错误[E0382]:使用移动值:`iy`
-->src/lib.rs:7:18
|
1 | fn代表_xy(ix:I,iy:I,f:f)
|--发生移动是因为'iy'具有类型'I',该类型不实现'Copy'特性
...
7 |在iy中为y{
|^^^`iy`由于在循环的上一次迭代中对`.into_iter()`的隐式调用而移动
|
注意:此函数获取接收者'self'的所有权,该接收者移动'iy'`
帮助:考虑借用以避免进入for循环
|
7 |适用于y in和iy{
|                  ^^^
帮助:考虑进一步限制这个界限
|
3 | I:迭代器+副本,
|                               ^^^^^^

如何更正此程序?

当您运行
for
循环时,您传递的iterable参数将被“移入”
for
循环;迭代完成后,迭代器将被删除。如果要使迭代器可重用,典型的方法是添加一个
Clone
绑定。此外,原则上,您将遇到相同的问题(相反)使用
ix
迭代器中的
x
项:因为在
iy
循环的每次迭代中都要重用它们,所以需要确保它们可以被克隆或复制。这一问题不会发生在可复制的
usize
中,但更通用的版本需要包含
Clone
Copy
绑定在
ix::Item

fn表示_xy(ix:X,iy:Y,f:f)
哪里
X:迭代器,
X::项:克隆,
Y:迭代器+克隆,
F:FnMut(X::Item,Y::Item)
) -> {
对于ix中的x{
对于iy.clone()中的y{
f(x.clone(),y)
}
}
}

实际上,在Rust中遇到的大多数迭代器都是廉价可克隆的。集合迭代器(如
Vec::iter
HashMap::iter
)包含对底层集合的简单引用,以及大多数迭代器适配器(
map
filter
),等等)只要所使用的迭代器也是一样,就可以廉价地克隆。迭代器只能迭代一次。您的代码多次迭代
iy
,对
ix
中的每个项迭代一次。我建议接受切片而不是迭代器,因为它们可以多次迭代。另一种方法可能是需要
iterator
和使用
iy.copied()
。如果您的迭代器是Copy,您可能可以通过要求I:Copy来解决它。您可以-许多迭代器(包括在
Vec
s上迭代的迭代器)正在请求
Clone
(以及在
iy.Clone()
上迭代)优于
Copy
,因为更多类型实现了
Clone
。其中一种类型是
std::ops::Range
,它似乎很可能被传递给这样的函数。