首页 > 解决方案 > 意外的“找不到方法”编译器错误

问题描述

这个问题源于我对cartesian_productfromitertoolsinto_par_iterRayon 的使用(在一个学习 Rust 的玩具项目中)。我的问题不是关于这个特定的代码,而是关于阅读 rustc 错误消息和 Rust 库文档的问题。

这按预期工作:

fn main() {
    let it = 0..15;
    it.into_par_iter().for_each(|x| println!("{:?}", x));
}

但是下面的代码无法编译并显示错误。Product返回的文档cartesian_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:\rust\iters)
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
   --> src\main.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:\rust\dot.cargo\registry\src\github.com-1ecc6299db9ec823\itertools-0.9.0\src\adaptors\mod.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`

标签: rustitertoolsrayon

解决方案


itertools::Itertools::cartesian_product返回一个 type 的值itertools::Product,它实现了 std's Iterator

然而,Rayon 不能只与任何实现的类型一起工作Iterator——它还必须实现rayon::ParallelIterator. Rayon 恰好ParallelIterator为大多数 std 迭代器提供了实现,但它不能在itertools不依赖于该板条箱的情况下为另一个板条箱(如 )中的结构实现它们。同样,itertools如果不rayon::ParallelIterator依赖rayon.

Itertools::cartesian_product相反,您可以使用 Rayon 的 API复制自己的功能:

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));
}

推荐阅读