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

How to define a generic function that takes a function that converts a slice to an iterator

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

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, 2, 3, 4];

    make_iter(&mut data);
}
应该使用

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

更新:

要处理的切片应该被认为是在 foo 函数内部动态生成的,并在处理后被丢弃。

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

data 的生命周期与函数 foo 相同,因为它是在函数 foo 中创建的。但是,闭包的生命周期比变量 data 长,因为闭包作为参数传入 foo,因此它的生命周期比 data 长。当函数 foo 超出范围时, data 被删除。那么你的闭包正在尝试 return 一个已经被删除的引用 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, 2, 3, 4];

    make_iter(data);
}

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

rustplay ground link : 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, 2, 3, 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, 2, 3, 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, slice: &'a mut [i32]) -> Self::Iter;
}

fn foo(mut make_iter: impl for<'a> MakeIter<'a>) {
    let mut data = [1, 2, 3, 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);
}