Как обернуть не объектобезопасную черту в объектобезопасную? - PullRequest
4 голосов
/ 24 октября 2019

Первоначально я столкнулся с этой проблемой при попытке создать 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, в новую, безопасную для объекта,так что мы можем, например, выполнить динамическую операцию над ним, как в примере выше?

...