映射到无克隆的载体

时间:2019-06-03 05:34:37

标签: rust

我正在尝试使用此签名编写函数,而不使用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的签名更改为例如使用可变函数,如果可能的话,我希望它看起来像是外部的纯函数,只是利用内部的突变,因为我们可以避免使用它,因为调用者已将对象的所有权传递给我们。

2 个答案:

答案 0 :(得分:5)

您实际上遇到了replace_withtake_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);
}