Первоначально я столкнулся с этой проблемой при попытке создать Rayon ParallelIterator, в котором операция flat_map
применялась к динамическому числу раз см. Этот пост на трекере проблем Rayon .
Примечание: я задавал тот же вопрос и на форуме пользователей Rust ( см. Здесь ), но StackOverflow может быть лучшим местом для этого вопроса.
Для стандартных(то есть выполняются последовательно) Iterator
s следующие работы:
fn fancy<Input, Output, Item>(input: Input, depth: usize) -> Output
where
Input : IntoIterator<Item = Item>,
Output : std::iter::FromIterator<Item>,
Item : Copy + std::ops::Add<Output = Item>,
{
let mut iter: Box<dyn Iterator<Item = Item>> = Box::new(input.into_iter());
for _ in 0..depth {
iter = Box::new(iter.flat_map(|x| vec![x, x + x].into_iter()));
}
iter.collect()
}
Однако при работе с Rayon's ParallelIterator
s дела обстоят ненадежно: ParallelIterator
требует, чтобы типы, реализующие его, были Sized
, что делает их не объектными, безопасными и, следовательно, невозможными для передачи в качестве признака объекта. Таким образом, следующий прямой перевод не работает:
use rayon::prelude::*;
fn fancy2<Input, Output, Item>(input: Input, depth: usize) -> Output
where
Input : IntoParallelIterator<Item = Item>,
Output : FromParallelIterator<Item>,
Item : Copy + std::ops::Add<Output = Item> + Send,
{
let mut iter: Box<dyn rayon::iter::ParallelIterator<Item = Item>> = Box::new(input.into_par_iter());
for _ in 0..depth {
iter = Box::new(iter.flat_map(|x| vec![x, x + x].into_par_iter()));
}
iter.collect()
}
Мой вопрос таков: как мы можем обернуть небезопасную черту, такую как ParallelIterator
, в новую, безопасную для объекта,так что мы можем, например, выполнить динамическую операцию над ним, как в примере выше?