具有生命周期的 Rust iter-map-collect 模式

问题描述 投票:0回答:1

我正在尝试实现我经常使用的

Vec.iter().map(...).collect()
模式的快捷方式。乍一看,并不难:

pub trait IterMap<T> {
    fn mapcollect<F, U>(&self, f: F) -> Vec<U>
    where
        F: Fn(&T) -> U;
}

impl<T> IterMap<T> for Vec<T> {
    fn mapcollect<F, U>(&self, f: F) -> Vec<U>
    where
        F: Fn(&T) -> U,
    {
        self.iter().map(f).collect()
    }
}

对于简单的案例来说,它就像一个魅力:

let v = vec![5; 5];
let v_2 = v.mapcollect(|x| x * x);

但是,如果涉及生命周期,它就会崩溃:

let v: Vec<Vec<i32> = ...; // define 2D-vector here
let v_slice: Vec<&[i32]> = v.mapcollect(|x| x.as_slice());

原因是 Rust 无法通过我的

v_slice
抽象将
v
的生命周期与
mapcollect()
的生命周期联系起来。

当然,我可以使用适当的生命周期注释来实现另一个

mapcollect_with_lifetime(...)
,但这种方法有几个缺点。有没有办法帮助 Rust 自动计算出生命周期,就像原来的
iter().map(...).collect()
那样?

generics rust lifetime
1个回答
0
投票

您根本不需要第二次实现,您可以使用单个正确实现的特征和实现来完成此操作。这是因为将生命周期添加到您的实现中您如何帮助 rust 自动为调用者计算出这一点。

pub trait IterMap<'a, T: 'a> {
    fn mapcollect<F, U>(&'a self, f: F) -> Vec<U>
    where
        F: Fn(&'a T) -> U,
        U: 'a;
}

impl<'a, T: 'a> IterMap<'a, T> for Vec<T> {
    fn mapcollect<F, U>(&'a self, f: F) -> Vec<U>
    where
        F: Fn(&'a T) -> U,
        U: 'a,
    {
        self.iter().map(f).collect()
    }
}

fn main() {
    let v = vec![5; 5];
    let v_2 = v.mapcollect(|x| x * x);

    let v: Vec<Vec<i32>> = vec![vec![1, 2, 3], vec![4, 5, 6]];

    let v_slice: Vec<&[i32]> = v.mapcollect(|x| x.as_slice());
}

© www.soinside.com 2019 - 2024. All rights reserved.