fold 对它接受的闭包很挑剔
fold is picky about closures it accepts
(这里是 rust noob;我试图了解在高阶函数情况下 can/cannot/should/shouldn 不能通过引用传递的内容)
let a = [1, 2, 3];
此调用有效:
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`.
该解释没有提供任何有趣的内容。它表示闭包的参数与 fold
的参数不匹配。但是,我看不出它是如何从 fold
:
的声明中得出的
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B
为什么第二个参数应该是 &{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);
第三种形式永远行不通。闭包需要能够 return 一个新值来更新累加器。累加器的类型是i32
。它不能是引用,因为你不能 return 来自闭包的引用(原始值将被删除,Rust 不会让你 return 悬空指针)。
查看fold()
的声明
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B
你可以看到函数有两个泛型类型参数——累加器的类型B
和闭包的类型F
。闭包类型具有 trait bound FnMut(B, Self::Item) -> B
,这意味着第一个参数的类型与累加器的类型相同,而第二个参数的类型是迭代器的项类型。
在调用中
let sum = a.iter().fold(0, |acc, x| acc + x);
我们使用项目类型为 &i32
的迭代器,并且您的累加器被初始化为 0
,因此它的类型被推断为 i32
(这是默认的整数类型在没有任何进一步资格的情况下)。
(这里是 rust noob;我试图了解在高阶函数情况下 can/cannot/should/shouldn 不能通过引用传递的内容)
let a = [1, 2, 3];
此调用有效:
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`.
该解释没有提供任何有趣的内容。它表示闭包的参数与 fold
的参数不匹配。但是,我看不出它是如何从 fold
:
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B
为什么第二个参数应该是 &{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);
第三种形式永远行不通。闭包需要能够 return 一个新值来更新累加器。累加器的类型是i32
。它不能是引用,因为你不能 return 来自闭包的引用(原始值将被删除,Rust 不会让你 return 悬空指针)。
查看fold()
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B
你可以看到函数有两个泛型类型参数——累加器的类型B
和闭包的类型F
。闭包类型具有 trait bound FnMut(B, Self::Item) -> B
,这意味着第一个参数的类型与累加器的类型相同,而第二个参数的类型是迭代器的项类型。
在调用中
let sum = a.iter().fold(0, |acc, x| acc + x);
我们使用项目类型为 &i32
的迭代器,并且您的累加器被初始化为 0
,因此它的类型被推断为 i32
(这是默认的整数类型在没有任何进一步资格的情况下)。