Rust 无法将iter()转换为人造丝折叠(..)';s par_iter()折叠(…)

Rust 无法将iter()转换为人造丝折叠(..)';s par_iter()折叠(…),rust,Rust,我试图使用它来启动一系列顶级线程,以递归方式调用模拟函数。该代码在使用channel send&receive时工作,因此与多线程兼容,但无法使用par_iter()进行编译 fn模拟(初始板:&board,玩家:玩家,级别:u32,开始:bool)->选项{ ... #[在线(始终)] fn评估移动(上一个:选项,新移动:&AMove,新移动分数:i32,玩家:玩家)->AMove{ ... } ... let accumlator=| previous:Option,a|move:&Opt

我试图使用它来启动一系列顶级线程,以递归方式调用模拟函数。该代码在使用channel send&receive时工作,因此与多线程兼容,但无法使用
par_iter()
进行编译

fn模拟(初始板:&board,玩家:玩家,级别:u32,开始:bool)->选项{
...
#[在线(始终)]
fn评估移动(上一个:选项,新移动:&AMove,新移动分数:i32,玩家:玩家)->AMove{
...
}
... 
let accumlator=| previous:Option,a|move:&Option |如果让某些(AMove{board:ref a|board,…})=*a|move{
...
}否则{
以前的
};
如果开始&&!获胜{
移动=移动.par_iter().折叠(移动,累加器);
}否则{
移动=移动.iter().折叠(移动,累加器);
}
行动
}
我在使用par_iter()时遇到一个编译器错误,我不知道如何修复这些错误

error[E0277]:未满足特性绑定'std::option::option:std::ops::Fn'
-->src/main.rs:271:37
|
271 |移动=moves.par_iter().折叠(移动,累加器);
|^^^^特性'std::ops::Fn'未为'std::option::option'实现`
错误[E0277]:未满足特性绑定的'std::option::option:std::ops::FnOnce'
-->src/main.rs:271:37
|
271 |移动=moves.par_iter().折叠(移动,累加器);
|^^^^特性'std::ops::FnOnce'未为'std::option::option'实现`
错误[E0308]:类型不匹配
-->src/main.rs:271:20
|
271 |移动=moves.par_iter().折叠(移动,累加器);
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^`
|
=注意:应为'std::option::option'类型`

发现类型'rayon::iter::Foldrayon的
Fold
需要一个生成标识元素的函数,而不是单个基本元素。在您的情况下,如果
AMove
Copy+Send+Sync
,只需执行
moves.par_iter()。折叠(|移动,累加器)
就足够了

如果
AMove
不是
Copy
,请使用
| move.clone()

Rayon可能希望生成多个标识元素来并行执行不同的块,并且只在最后合并结果,这就是为什么它需要能够生成所需数量的标识元素

检查
折叠
。此外,如果累加器返回的类型与identity元素相同,则可能需要使用
reduce
(有关差异,请参阅链接文档)


另一个问题是,您不能以您尝试的方式使用递归闭包(Rust就是做不到这一点)。请为累加器使用命名函数

解决方案在于对产生的
折叠使用
reduce
。谢谢你的暗示。我终于在人造丝演示中找到了一个例子,为我的案例解决方案铺平了道路。以下是今后参考的方法

moves.par_iter()
     .fold(|| None, accumlator)
     .reduce(|| None, |previous: Option<AMove>, a_move: Option<AMove>| {
        if let Some(a_move) = a_move {
            Some(select_move(&previous, &a_move, player))
        } else {
            previous
        }
    })
moves.par_iter()
.折叠(| |无,累加器)
.减少(| |无,|上一个:选项,a|U移动:选项|{
如果让一些人(移动)=移动{
一些(选择移动(&上一步,&移动,玩家))
}否则{
以前的
}
})

最令人费解的错误是最初出现的错误,因为我使用的是
折叠(a,b)
而不是
折叠(| a,b)
,它抱怨
Fn
FnOnce
,让我不知所措。

欢迎使用堆栈溢出!寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。否则,您的问题很可能会以如下方式结束。我的期望是,par_iter()的“行为”与“iter()”相同,或者是实现类似行为的建议。@SergeRobyns请阅读并回答。情况正在好转。AMove确实有复制和克隆:#[派生(调试,复制,克隆)]结构AMove{column:usize,board:board,score:i32,累计_score:i32,累计_moves:i32,}尽管如此,我试图使用你的par_iter版本,但我现在遇到了另一种错误。医生对我的情况帮助不大。这个错误暗示我需要“折叠”折叠的结果,就像doc声明的一样,但是doc使用sum函数作为示例,我不需要它。The_move=moves.par_iter().fold(| | The | u move,acumlator);预期的enum
std::option::option
,找到的struct
rayon::iter::Fold
是否尝试改用reduce?Fold将为您提供另一个结果迭代器,然后您可以以某种方式手动合并(例如使用reduce)。如果累加器是关联的并返回AMove,那么您肯定应该使用reduce而不是fold。基于您的所有输入和人造丝演示中的一个示例,我现在使用par_iter(…).fold(| | |…).reduce(| | |…)并且它可以工作。
moves.par_iter()
     .fold(|| None, accumlator)
     .reduce(|| None, |previous: Option<AMove>, a_move: Option<AMove>| {
        if let Some(a_move) = a_move {
            Some(select_move(&previous, &a_move, player))
        } else {
            previous
        }
    })