提问人:YEp d 提问时间:9/1/2023 更新时间:9/1/2023 访问量:65
如何在 Rust 中“矢量化”函数
How to "vectorize" a function in Rust
问:
假设我想将一个对集合的两个元素进行操作的函数转换为对两个集合进行元素操作的函数。
例如,我想将一个函数将两个数字相加,变成一个函数,该函数接受两个数字集合并将数字按元素相加。为了在不重复代码的情况下做到这一点,我尝试实现一个接受闭包的函数:
fn vectorize<F, H, U, J>(f: F) -> impl Fn(H, H) -> J
where
F: FnMut((H::Item, H::Item)) -> U,
H: IntoIterator,
J: FromIterator<U>
{ |x, y| {x.into_iter().zip(y).map(f).collect()} }
comipler 给出:
error[E0507]: cannot move out of `f`, a captured variable in an `Fn` closure
--> src/main.rs:10:40
|
5 | fn vectorize<F, H, U, J>(f: F) -> impl Fn(H, H) -> J
| - captured outer variable
...
10 | { |x, y| {x.into_iter().zip(y).map(f).collect()} }
| ------ ^ move occurs because `f` has type `F`, which does not implement the `Copy` trait
| |
| captured by this `Fn` closure
这不起作用,因为闭包已通过该方法移出返回的闭包。但实际上,这样的函数应该是可以编写的,因为无论在不同的迭代器上使用多少次,它都是有效的。f
map
f
FnMut
如何编写这种类型的函数,使其不会导致此类错误?
答:
4赞
cafce25
9/1/2023
#1
你想在这里改变三件事。
- 你不能把a转换成a,所以你也必须返回。
FnMut
Fn
impl FnMut
- 在闭包之前添加,以便它拥有
move
f
- 你不能传递给 map,因为这必然会移动它,但你不能从一个只在你的代码或固定代码中实现的闭包中移动。相反,传递对它的引用(只有可变引用也实现
FnMut
,并且要传递可变引用,您还必须使可变):f
Fn
FnMut
f
fn vectorize<F, H, U, J>(mut f: F) -> impl FnMut(H, H) -> J
where
F: FnMut((H::Item, H::Item)) -> U,
H: IntoIterator,
J: FromIterator<U>,
{
move |x, y| x.into_iter().zip(y).map(&mut f).collect()
}
您可能还需要添加第二个类型参数,以便也可以将 2 种不同类型的集合与可能不同的类型合并。: IntoIterator
评论
0赞
YEp d
9/1/2023
为什么在这种情况下需要可变?另外,一旦 x 和 y 被移动到闭包中,这个函数会消耗它们吗?f
评论