Hi there, I'm trying to determine if what I'm attempting is possible. My intent is to, using rayon, run a number of functions concurrently that take no input and produce the same result. Given:
// Imagine this being some arbitrarily expensive function.
fn bar(n: u32) -> u32 {
n + 1
}
The first step I'd take is to naively shove closures in a vec![] and call it a day:
let foo = vec![|| bar(1), || bar(2), || bar(3)];
but
|
118 | let foo = vec![|| bar(1), || bar(2), || bar(3)];
| ^^^^^---------^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | the expected closure
| expected slice, found array of 3 elements
|
= note: expected struct `Box<[[closure@src/main.rs:118:20: 118:29]], _>`
found struct `Box<[fn() -> u32; 3], std::alloc::Global>`
Let's help Rust with the inference:
let zoo: Vec<dyn FnOnce() -> u32> = vec![|| bar(1), || bar(2), || bar(3)];
but
error[E0277]: the size for values of type `dyn FnOnce() -> u32` cannot be known at compilation time
--> src/main.rs:117:41
|
117 | let zoo: Vec<dyn FnOnce() -> u32> = vec![|| bar(1), || bar(2), || bar(3)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn FnOnce() -> u32`
= note: slice and array elements must have `Sized` type
let foo: Vec<Box<dyn FnOnce() -> u32>> = vec![
Box::new(|| bar(1)),
Box::new(|| bar(2)),
Box::new(|| bar(3)),
];
Okay! This actually compiles! Although I'm not sure why, given the threat of Sized in the previous compile error and that I can't see Sized listed in Box's docs. Well, no matter, sally forth:
use rayon::prelude::*;
foo.into_par_iter().for_each(|f| f());
but
error[E0599]: no method named `into_par_iter` found for struct `Vec<Box<dyn FnOnce() -> u32>>` in the current scope
--> src/main.rs:140:9
|
140 | foo.into_par_iter().for_each(|f| f());
| ^^^^^^^^^^^^^ method not found in `Vec<Box<dyn FnOnce() -> u32>>`
|
= note: the method `into_par_iter` exists but the following trait bounds were not satisfied:
`[Box<dyn FnOnce() -> u32>]: Sized`
which is required by `[Box<dyn FnOnce() -> u32>]: rayon::iter::IntoParallelIterator`
`[Box<dyn FnOnce() -> u32>]: rayon::iter::ParallelIterator`
which is required by `[Box<dyn FnOnce() -> u32>]: rayon::iter::IntoParallelIterator`
Arg. So why is it complaining about Sized again now?
For now we can ignore that the for_each doesn't do anything, and that I'm likely invoking the f() incorrectly. At the moment I can't see why Rayon wouldn't want elements of Box like this. Is what I'm attempting fundamentally impossible? Thank you kindly.