rust 有没有一种方法可以在 * 不可克隆 * 的迭代器上实现一个Caribbean产品?

bwitn5fc  于 2023-11-19  发布在  其他
关注(0)|答案(2)|浏览(114)

这个想法是,我想要所有Box迭代器的carryover乘积<dyn...>,因为我有一个更高的函数,它返回不同类型的迭代器,其中一些必须通过carryover乘积函数运行。然而,我遇到了借用检查器的问题,因为Box<dyn ..>是不可克隆的。有什么办法可以解决这个问题吗?
代码:

fn cartesian_product<'a>(iterators: &'a mut Vec<Box<dyn Iterator<Item = Sexp> + 'a>>) -> Box<dyn Iterator<Item = Vec<Sexp>> + 'a> {
        if let Some(iter) = iterators.pop() {
            let current_iterator = iter.map(|val| vec![val]);
            let child_iterators = (Self::cartesian_product(iterators));
            let combined_iterators = current_iterator.flat_map(move |vec| { 
                
                let val = child_iterators.map(move |item| 
                    {
                        let mut vec_cloned = vec.clone();
                        let mut item_cloned = item.clone();
                        item_cloned.append(&mut vec_cloned);
                        item_cloned
                    });
                val 
            });
            Box::new(combined_iterators)
        }
        else {
            Box::new(std::iter::empty())
        }
    }

字符串
Bug目前:

cannot move out of `child_iterators`, a captured variable in an `FnMut` closure
move occurs because `child_iterators` has type `Box<dyn Iterator<Item = Vec<sexp::Sexp>>>`, which does not implement the `Copy` trait


我尝试了上面的函数,以及一个自定义迭代器,它也很难使用借用检查器。
先说清楚,我不想打对方付费电话。

t9aqgxwy

t9aqgxwy1#

有许多策略可以使用。
首先,可能最有效的方法是将两个迭代器收集到Vec s中,然后iter()它并在其上调用cartesian_product()。但是,如果迭代器非常大,这将不起作用。
特别是,只需要一个迭代器是Clone,所以你可以收集其中较短的。
另一种策略是使用一个自定义trait,它的超trait是Iterator,但也可以克隆为dyn Trait。关于如何做到这一点,请参阅How to clone a struct storing a boxed trait object?

kxeu7u2r

kxeu7u2r2#

非常受诅咒的代码,但工作

use std::iter;

struct IterRestart<I: Iterator> {
    original: I,
    current: iter::Peekable<I>,
}

impl<I: Clone + Iterator> IterRestart<I>
where
    I::Item: Clone,
{
    fn new(iter: I) -> Self {
        Self {
            original: iter.clone(),
            current: iter.peekable(),
        }
    }

    fn boxed<'a>(iter: I) -> Box<dyn CartesianIterator<Item = I::Item> + 'a>
    where
        I: 'a,
    {
        Box::new(Self::new(iter))
    }
}

impl<I: Iterator> Iterator for IterRestart<I> {
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.current.next()
    }
}

impl<I: Clone + Iterator> CartesianIterator for IterRestart<I>
where
    I::Item: Clone,
{
    fn restart(&mut self) {
        self.current = self.original.clone().peekable();
    }

    fn current(&mut self) -> Option<Self::Item> {
        self.current.peek().cloned()
    }
}

trait CartesianIterator: Iterator {
    fn restart(&mut self);
    fn current(&mut self) -> Option<Self::Item>;
}

fn cartesian_product<E: Clone>(
    mut iterators: Vec<Box<dyn CartesianIterator<Item = E>>>,
) -> impl Iterator<Item = Vec<E>> {
    let mut buffer = iterators
        .iter_mut()
        .filter_map(|iter| iter.current())
        .collect::<Vec<_>>();
    iter::from_fn(move || {
        if buffer.len() != iterators.len() {
            return None;
        }

        iterators
            .iter_mut()
            .enumerate()
            .rev()
            .find_map(|(i, iter)| {
                iter.next();
                let no_current = iter.current().is_none();
                if no_current {
                    iter.restart();
                }
                buffer[i] = iter.current().unwrap();
                (!no_current).then_some(())
            })?;

        Some(buffer.clone())
    })
}

fn main() {
    let nums = 0..4;
    let stepped_nums = (0..8).step_by(2);
    let eh = vec![0, 17, 26];
    let mut iter = cartesian_product(vec![
        IterRestart::boxed(nums),
        IterRestart::boxed(stepped_nums),
        IterRestart::boxed(eh.into_iter()),
    ]);

    while let Some(pair) = iter.next() {
        println!("{:?}", pair);
    }
}

字符串

相关问题