2017-01-10 1 views
1

Это надуманный пример, но я верю, что если я смогу получить эту работу, я могу применить его к моему конкретному случаю.Как использовать файл .par_iter() с помощью вектора дженериков?

extern crate num; 
extern crate rayon; 
use rayon::prelude::*; 
use num::Float; 

fn sqrts<T: Float>(floats: &Vec<T>) -> Vec<T> { 
    floats.par_iter().map(|f| f.sqrt()).collect() 
} 

fn main() { 
    let v = vec![1.0, 4.0, 9.0, 16.0, 25.0]; 
    println!("{:?}", sqrts(&v)); 
} 

Это ошибки во время компиляции с «метод par_iter существует, но в следующих пределах признака не были удовлетворены: &std::vec::Vec<T> : rayon::par_iter::IntoParallelIterator». Код работает нормально, если я использую iter вместо par_iter, или если я переключусь на использование f32 или f64 вместо общего.

Что я могу сделать, чтобы использовать par_iter на вектор дженериков? Является ли признак IntoParallelIterator конечным пользователем? Как мне это сделать?

ответ

4

Сначала прочитайте Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument?. Тогда ...

Пересмотреть реализаторы из IntoParallelIterator:

impl<'data, T: Sync + 'data> IntoParallelIterator for &'data [T] 

Sync Добавление связанных исправления этой проблемы. Район работает потенциально с использованием нескольких потоков, но ваш оригинал T не дает никаких гарантий относительно того, безопасно ли делиться или между потоками! Это приходит во второй раз:

error: no method named `collect` found for type `rayon::par_iter::map::Map<rayon::par_iter::slice::SliceIter<'_, T>, rayon::par_iter::map::MapFn<[[email protected]/main.rs:7:27: 7:39]>>` in the current scope 
--> src/main.rs:7:41 
    | 
7 |  floats.par_iter().map(|f| f.sqrt()).collect() 
    |           ^^^^^^^ 
    | 
    = note: the method `collect` exists but the following trait bounds were not satisfied: `rayon::par_iter::map::MapFn<[clos[email protected]/main.rs:7:27: 7:39]> : rayon::par_iter::map::MapOp<&_>`, `rayon::par_iter::map::Map<rayon::par_iter::slice::SliceIter<'_, T>, rayon::par_iter::map::MapFn<[[email protected]/main.rs:7:27: 7:39]>> : std::iter::Iterator` 

Покидает collect:

fn collect<C>(self) -> C 
    where C: FromParallelIterator<Self::Item> 

Мы можем видеть, что целевой тип должен реализовывать FromParallelIterator:

impl<T> FromParallelIterator<T> for Vec<T> where T: Send 

Таким образом, добавление обе границы позволяет его составление:

fn sqrts<T: Float + Send + Sync>(floats: &[T]) -> Vec<T> 
+0

Я предполагаю, что это следует за std lib, в котором 'collect' делегирует реализацию' itXerX'' от XXX' ... но здесь нет ничего, что указывало бы мне на поиск «FromParallelIterator» для подсказки, которая помогает исправить проблему. Ну, в любом случае, не в прямом направлении. –

+0

@SimonWhitehead hmm. Я забыл добавить эту часть к моему ответу, но это все еще немного пусто. Сообщение об ошибке указывает «Карта», поскольку не реализует «собирать», но на самом деле это не значит, что «Map» виноват ... – Shepmaster

+0

А, теперь я вижу это с вашими обновлениями. Если бы я не был настолько одержим Рустом, я, конечно, был бы очень смущен ошибкой здесь и, вероятно, сдался. Иногда очень понятно, почему так много людей бросают Rust через короткое время. Спасибо за редактирование, чтобы сделать его немного понятнее! –

Смежные вопросы