微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何定义一个通用函数,该函数采用将切片转换为迭代器的函数

如何解决如何定义一个通用函数,该函数采用将切片转换为迭代器的函数

我想编写一个函数,以不同的顺序处理一些切片,所以我决定编写一个在迭代顺序上通用的函数,例如:

fn foo<'a,I: Iterator<Item = &'a mut i32>>(make_iter: impl Fn(&'a mut [i32]) -> I) {
    let mut data = [1,2,3,4];

    make_iter(&mut data);
}

fn main() {
    foo(|x| x.iter_mut());
    foo(|x| x.iter_mut().rev());
}

这会导致“借来的价值寿命不够长”错误

我想像这样

fn foo(make_iter: impl for<'a> Fn(&'a mut [i32]) -> impl Iterator<Item = &'a mut i32>) {
    let mut data = [1,4];

    make_iter(&mut data);
}

应该被使用,但 impl Iterator 在那个位置是不允许的。那么我有什么可以做的吗?

更新:

要处理的切片应被视为在 foo 函数内部动态生成,并在处理后删除

解决方法

你的函数大部分是正确的。编译错误“借用的值寿命不够长”是由于您在 foo 中定义数据而不是将其传入。错误是由于行let mut data = [1,2,3,4];>

data 的生命周期与函数 foo 相同,因为它是在函数 foo 中创建的。然而,闭包的生命周期比变量 data 长,因为闭包作为参数传入 foo,因此它的生命周期比 data 长。当函数 foo 超出范围时,data 被删除。然后你的闭包试图返回一个已经被删除的引用 data。这就是为什么你编译错误“借来的价值活得不够长”。

您可以通过将数据作为参数传递到 foo 来进行编译,在这种情况下,您不会因生命周期而出现问题。

下面的代码将被编译。

fn foo<'a,I: Iterator<Item = &'a mut i32>>(make_iter: impl Fn(&'a mut [i32]) -> I,data: &'a mut Vec<i32>) {
    // let mut data = [1,4];

    make_iter(data);
}

fn main() {
    let mut data= vec![1,4];
    foo(|x| x.iter_mut(),&mut data);
    foo(|x| x.iter_mut().rev(),&mut data);
}

rustplay 地面链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8b263451fcb01518b3f35bda8485af9c


更新:请尽量误解您的要求。我试图找到一种干净的方式来写这个,但我能想到的最好的方法是使用 Box<dyn 来做。我知道 Box<dyn... 有运行时成本,但我想不出更好的方法来使用 impl Iterator

使用 Box<dyn ... 的实现是

fn foo<F>(make_iter: F) where for<'a> F: Fn(&'a mut [i32])->Box<dyn Iterator<Item=&'a mut i32>+'a>{
    let mut data = vec![1,4];

    make_iter(&mut data);
}


fn main() {
    foo(|x| Box::new(x.iter_mut()));
    foo(|x| Box::new(x.iter_mut().rev()));
}
,

我想出了一个解决方案:

use std::iter::Rev;
use std::slice::IterMut;

trait MakeIter<'a> {
    type Iter: Iterator<Item = &'a mut i32>;

    fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter;
}

fn foo(mut make_iter: impl for<'a> MakeIter<'a>) {
    let mut data = [1,4];

    make_iter.make_iter(&mut data);
}

struct Forward;

impl<'a> MakeIter<'a> for Forward {
    type Iter = IterMut<'a,i32>;

    fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter {
        slice.iter_mut()
    }
}

struct Backward;

impl<'a> MakeIter<'a> for Backward {
    type Iter = Rev<IterMut<'a,i32>>;

    fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter {
        slice.iter_mut().rev()
    }
}

fn main() {
    foo(Forward);
    foo(Backward);
}

但我不确定是否可以简化。

更新

这里是一个简化:

trait MakeIter<'a> {
    type Iter: Iterator<Item = &'a mut i32>;

    fn make_iter(&mut self,4];

    make_iter.make_iter(&mut data);
}

impl<'a,F,R> MakeIter<'a> for F
where
    F: FnMut(&'a mut [i32]) -> R,R: Iterator<Item = &'a mut i32>,{
    type Iter = R;

    fn make_iter(&mut self,slice: &'a mut [i32]) -> Self::Iter {
        self(slice)
    }
}

fn iter_forward(slice: &mut [i32]) -> impl Iterator<Item = &mut i32> {
    slice.iter_mut()
}

fn iter_backward(slice: &mut [i32]) -> impl Iterator<Item = &mut i32> {
    slice.iter_mut().rev()
}

fn main() {
    foo(iter_forward);
    foo(iter_backward);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。