我有一个Vec
盒装封口(Vec<Box<Fn(...) -> ...>>
)。我可以vec.into_iter().map(...)
,但我不能将它与 Rayon's 一起使用。into_par_iter
vec.into_par_iter().map(...)
这是一个最小化的示例(playground):
type GameResult<T> = Result<T, ()>;
type Game = ();
type PlayerId = String;
use rayon::prelude::*; // 1.5.1
fn main() {
// the type of our closures. It's boxed, so it's sized right?
type CpuOption = Box<dyn Fn(u32) -> GameResult<u32>>;
let mut options: Vec<CpuOption> = vec![];
options.push(Box::new(|i| Ok(i + 2)));
options.push(Box::new(|i| Ok(i + 3)));
let try_it = |option: CpuOption| -> GameResult<u32> { Ok(option(12)?) };
let parallel = true;
if parallel {
// ERROR IS HERE. says my type isn't sized?
let options = options
.into_par_iter()
.map(try_it)
.flat_map_iter(Result::into_iter);
let best_option = options.max_by_key(|score| *score).unwrap();
} else {
// but this works fine!
let options = options.into_iter().map(try_it).flat_map(Result::into_iter);
let best_option = options.max_by_key(|score| *score).unwrap();
}
}
我得到的错误:
Compiling playground v0.0.1 (/playground)
error[E0599]: the method `into_par_iter` exists for struct `Vec<Box<(dyn Fn(u32) -> Result<u32, ()> + 'static)>>`, but its trait bounds were not satisfied
--> src/lib.rs:24:14
|
24 | .into_par_iter()
| ^^^^^^^^^^^^^ method cannot be called on `Vec<Box<(dyn Fn(u32) -> Result<u32, ()> + 'static)>>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`[Box<dyn Fn(u32) -> Result<u32, ()>>]: Sized`
which is required by `[Box<dyn Fn(u32) -> Result<u32, ()>>]: rayon::iter::IntoParallelIterator`
`[Box<dyn Fn(u32) -> Result<u32, ()>>]: rayon::iter::ParallelIterator`
which is required by `[Box<dyn Fn(u32) -> Result<u32, ()>>]: rayon::iter::IntoParallelIterator`
我的印象是,将封口包裹在盒子中是使封口大小合适的解决方案,所以我在这里做到了。
如果我正确阅读了错误,[Box<dyn Fn(u32) -> Result<u32, ()>>]: Sized
则不满足,IntoParallelIterator
这是我所追求的先决条件。常规into_iter()
工作正常,因此 Rayon 设置了一些额外的限制。我预计人造丝会有更多的限制,但我认为这将是关于Send
我知道在这个最小的例子中我可以使用fn(...)
类型而不是Fn(...)
类型,因为它们不捕获任何值,但我的真实代码当然会捕获引用。
我正在使用 Rayon 为一个使用 minimax 风格的小游戏编写 AI,其中我有一个供 AI 尝试的事物列表,然后我在每件事之后观察得分。我希望这个递归调用堆栈的顶层在许多线程中启动顶层,但每个线程应该是顺序的。