Rust是一种多范例语言,因此它支持纯函数式编程(FP)语言的一些特性,其中就包括闭包。
在函数式编程语言中,如Haskell、Clojure、Erlang等,函数是最重要的部分,你可以将函数赋值给变量,将函数作为参数传递给其他函数,从其他函数返回。为了在Rust中提供同样的可能性,添加了闭包。
let simple_closure = || ();
simple_closure();
let add = |a, b| a + b;
println!("{}", add(1, 2)); // stdout: 3
闭包定义中的“|”与函数定义中的括号具有类似的作用。
在这里我们还可以看到与函数的另一个区别:Rust编译器可以在不明确指定参数类型的情况下推断参数类型,因此可以忽略它们。这在大多数情况下是正确的,但有时编译器可能会要求你显式地标注类型。
let closure = |x| x;
closure(3); // compiler infer int type
closure("hello from rusty closure"); // Error!
编译器在第三行期望参数为整数类型,但发现&str,所以出现类型不匹配错误。
1#[derive(Debug)]
2struct Point {
3 x: isize,
4 y: isize,
5}
6
7fn main() {
8 let point = Point { x: 6, y: 8 };
9 let dist = |point: Point| {
10 let squared_dist = point.x.pow(2) + point.y.pow(2);
11 let squared_dist = squared_dist as f32;
12 squared_dist.powf(0.5)
13 };
14 println!("{}", dist(point)); // Ok
15 println!("{:?}", point); // Error!
16}
首先,这个闭包有多行语句,所以它们出现在大括号中。其次,编译器不能推断参数类型,所以必须显式添加类型。
这段代码无法编译,这是因为closure成为Point参数的所有者,最后一行试图访问移动后的Point值,因此会导致程序失败。
1fn main() {
2 let a = 5;
3 let c = || println!("{}", a);
4 {
5 let a = 10;
6 c(); // stdout: 5
7 }
8}
1fn returns_closure() -> impl Fn() -> () {
2 || println!("Hello from closure")
3}
4
5fn takes_closure<F>(closure: F)
6where F: Fn()
7{
8 closure();
9}
10
11fn main() {
12 let closure = returns_closure();
13 takes_closure(closure);
14}
https://medium.com/@the.makcym/rust-understanding-closures-d037fb5c8177