我正在尝试使用此签名编写函数,而不使用clone()
或分配新的向量:
fn mapVec(f: Fn(T) -> T, x: Vec<T>) -> Vec<T>
在我看来,这似乎是可行的。对于x
中的每个元素,我们将其传递给f
,其中f
对其拥有所有权。然后,我们产生一个返回值,然后由于f
已拥有此传递值的所有权,如有必要,它将销毁它。然后,我们将返回值放回向量中。由于我们拥有x
的所有权,因此我们可以对其进行修改,然后将其返回给调用方。
我的尝试如下:
for e in x.iter_mut() {
*e = f(e);
}
return x;
但不幸的是,f
期望的是T
,而不是&mut T
。
我不想将mapVec
的签名更改为例如使用可变函数,如果可能的话,我希望它看起来像是外部的纯函数,只是利用内部的突变,因为我们可以避免使用它,因为调用者已将对象的所有权传递给我们。
答案 0 :(得分:5)
您实际上遇到了replace_with
和take_mut
板条箱试图解决的问题。只需将其中一个板条箱的使用放入循环中即可解决您的问题。
请注意这些警告。如果地图回调出现紧急情况,则会发生不良情况。这是因为您要执行的操作是将对象移出其位置,调用一个函数,然后将结果放回该位置。但是,如果该函数未产生结果(即出现紧急情况),您会在空白位置放置什么?
答案 1 :(得分:0)
此工作示例中的唯一区别在于,回调函数引用的是T
而不是T
本身,但仍然不是可变的:
fn map_vec<F, T>(f: F, x: Vec<T>) -> Vec<T>
where
F: Fn(&T) -> T,
{
let mut x = x;
for e in x.iter_mut() {
*e = f(e);
}
x
}
fn main() {
let x = vec![1, 2, 3];
let y = map_vec(|e| e + 1, x);
println!("{:?}", y);
}