这个问题源于我(在学习Rust的玩具项目中(使用itertools
的cartesian_product
和Rayon的into_par_iter
。我的问题不是关于这个特定的代码,而是关于阅读rustc错误消息和Rust库文档的问题。
如预期:
fn main() {
let it = 0..15;
it.into_par_iter().for_each(|x| println!("{:?}", x));
}
但是下面的代码未能编译,并显示错误。cartesian_product
返回的Product
的文档包括Iterator
的实现,所以我本以为into_par_iter
方法调用会进行类型检查,但事实并非如此。
以下是失败代码和由此产生的错误消息:
fn main() {
let it = (0..15).cartesian_product(0..8);
it.into_par_iter().for_each(|x| println!("{:?}", x));
}
Compiling iters v0.1.0 (D:rustiters)
error[E0599]: no method named `into_par_iter` found for struct `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>` in the current scope
--> srcmain.rs:8:8
|
8 | it.into_par_iter().for_each(|x| println!("{:?}", x));
| ^^^^^^^^^^^^^ method not found in `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>`
|
::: D:rustdot.cargoregistrysrcgithub.com-1ecc6299db9ec823itertools-0.9.0srcadaptorsmod.rs:288:1
|
288 | / pub struct Product<I, J>
289 | | where I: Iterator
290 | | {
291 | | a: I,
... |
294 | | b_orig: J,
295 | | }
| | -
| | |
| |_doesn't satisfy `_: rayon::iter::IntoParallelIterator`
| doesn't satisfy `_: rayon::iter::ParallelIterator`
|
= note: the method `into_par_iter` exists but the following trait bounds were not satisfied:
`itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
which is required by `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
`&itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
which is required by `&itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
`&mut itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
which is required by `&mut itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
itertools::Itertools::cartesian_product
返回类型为itertools::Product
的值,该值实现std的Iterator
。
然而,Rayon不能只处理任何实现Iterator
的类型,它还必须实现rayon::ParallelIterator
。Rayon恰好为大多数std迭代器提供了ParallelIterator
的实现,但如果不依赖于另一个机箱(如itertools
(中的结构,它就无法为其实现。类似地,itertools
不能在不依赖rayon
的情况下为其类型实现rayon::ParallelIterator
。
相反,您可以使用Rayon的API:自己复制Itertools::cartesian_product
的功能
use rayon::iter::{ParallelIterator, IntoParallelIterator};
fn main() {
(0..15).into_par_iter()
.flat_map(|i| (0..8).into_par_iter().map(move |j| (i, j)))
.for_each(|x| println!("{:?}", x));
}
或者,您可以从一个长度为(15*8(的迭代器开始,然后使用除法和余数将其分解为元组:
use rayon::iter::{ParallelIterator, IntoParallelIterator};
fn main() {
let it = (0 .. 15 * 8).into_par_iter().map(|x| (x / 8, x % 8));
it.for_each(|x| println!("{:?}", x));
}