Rust fold对它接受的闭包很挑剔

Rust fold对它接受的闭包很挑剔,rust,reference,fold,Rust,Reference,Fold,(这里是rust noob;我试图理解在高阶函数情况下什么可以/不能/应该/不应该通过引用传递) 此调用在以下情况下起作用: let sum = a.iter().fold(0, |acc: i32, x: &i32| acc + x); 这些不包括: let sum = a.iter().fold(0, |acc: i32, x: i32| acc + x); let sum = a.iter().fold(0, |acc: &i32, x: i32| acc + x);

(这里是rust noob;我试图理解在高阶函数情况下什么可以/不能/应该/不应该通过引用传递)

此调用在以下情况下起作用:

let sum = a.iter().fold(0, |acc:  i32, x: &i32| acc + x);
这些不包括:

let sum = a.iter().fold(0, |acc: i32, x: i32| acc + x);
let sum = a.iter().fold(0, |acc: &i32, x: i32| acc + x);
错误消息是

error[E0631]: type mismatch in closure arguments
 --> main.rs:8:22
  |
8 |   let sum = a.iter().fold(0, |acc: &i32, x: i32| acc + x);
  |                      ^^^^    --------------------------- found signature of `for<'r> fn(&'r i32, i32) -> _`
  |                      |
  |                      expected signature of `fn({integer}, &{integer}) -> _`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0631`.

为什么第二个参数应该是
&{integer}
,而第一个参数是
{integer}

迭代器中的项是从数组中借用的,
&i32
不是
i32
。此表单之所以有效,是因为累加器是自有的,而项目是借用的:

let sum = a.iter().fold(0, |acc: i32, x: &i32| acc + x);
您可以转换迭代器,以便复制它的项而不是引用它,然后第一个表单将工作:

let sum = a.iter().copied().fold(0, |acc: i32, x: i32| acc + x);

第三种形式永远行不通。闭包需要能够返回一个新值来更新累加器。蓄能器的类型为
i32
。它不能是引用,因为您无法从闭包返回引用(原始值将被删除,Rust不会让您返回悬空指针)。

迭代器中的项是从数组借用的,
&i32
不是
i32
。此表单之所以有效,是因为累加器是自有的,而项目是借用的:

let sum = a.iter().fold(0, |acc: i32, x: &i32| acc + x);
您可以转换迭代器,以便复制它的项而不是引用它,然后第一个表单将工作:

let sum = a.iter().copied().fold(0, |acc: i32, x: i32| acc + x);

第三种形式永远行不通。闭包需要能够返回一个新值来更新累加器。蓄能器的类型为
i32
。它不能是引用,因为您无法从闭包返回引用(原始值将被删除,Rust不会让您返回悬空指针)。

查看
fold()的声明


我们使用item类型为
&i32
的迭代器,累加器被初始化为
0
,因此它的类型被推断为
i32
(在没有任何进一步限定的情况下,这是默认的整数类型)。

查看
fold()的声明


我们使用item类型为
&i32
的迭代器,累加器被初始化为
0
,因此它的类型被推断为
i32
(在没有任何进一步限定的情况下,这是默认的整数类型)。

您可以从闭包返回引用,尽管它们的生存期需要超过闭包。示例`fn main(){let a=[1,2,3];let mut sum=0;let res=a.iter().copied().fold(&mut sum,| acc:&mut i32,x:i32 |->&mut i32{*acc+=x;acc});println!(“{}”,res)}`您可以从闭包返回引用,尽管它们的生存期需要超过闭包。示例`fn main(){let a=[1,2,3];let mut sum=0;let res=a.iter().copied().fold(&mut sum,| acc:&mut i32,x:i32 |->&mut i32{*acc+=x;acc});println!(“{}”,res)}`由于类型注释,累加器的类型被推断为i32。即使省略
acc:i32
注释,也会从
x:&i32
中推断出它,这不是因为它是默认值。累加器的类型会因为类型注释而推断为i32。即使省略
acc:i32
注释,也会从
x:&i32
中推断出来,这不是因为它是默认值。
fn fold<B, F>(self, init: B, f: F) -> B
where
    F: FnMut(B, Self::Item) -> B
let sum = a.iter().fold(0, |acc, x| acc + x);