closure闭包

闭包closure

捕获变量

闭包捕获变量采用了非常灵活的推导,可以根据需要,捕获外部变量的三种形式&T(borrow default)/&mut T(mut borrow)/T(move)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fn main() {
let greeting = "hello";
let mut farewell = "goodbye".to_owned();

let diary = || {
println!("I said {}.", greeting); // borrow

farewell.push_str("!!!");
println!("Then I screamed {}.", farewell); // mut borrow
println!("Now I can sleep. zzzzz");

// let _take = farewell; // uncomment this line to change farewell cature to `move`
};

diary();

println!("greeting: {}", greeting);
println!("farewell: {}", farewell); // if uncomment `drop(farewell)`
}
  1. 闭包默认通过borrow的方式捕获外部变量;
  2. 如果代码中包含了修改,那么编译器会自动的改成&mut T的形式。
  3. take同理如上;在闭包声明时,加上move修饰符,可以强制闭包拿走外部变量的所有权(force closure to take owership of capture)

闭包作为输入参数 Fn/FnMut/FnOnce

当把闭包作为输入参数的时候,由于闭包有三种捕获变量的形式,所以,函数声明时,必须指定闭包捕获变量的类型。

  1. Fn: the closure captures by reference (&T)
  2. FnMut: the closure captures by mutable reference (&mut T)
  3. FnOnce: the closure captures by value (T)
  • 注,rust编译器采用最少严格模式捕获变量
  • 简单来说,如果FnOnce标识闭包,那么闭包具有三种捕获方式,具体闭包内是如何使用的,编译器并不约束。

闭包作为输出参数

1
2
3
4
5
fn create_fn() -> impl Fn() {
let text = "Fn".to_owned();

move || println!("This is a: {}", text)
}
  1. impl Fn()当作出参;
  2. 必须要使用move标识闭包,因为捕获的变量,在函数结束时候就会失效,必须用move take its ownership.

高阶函数

高阶函数,值那些接收一个或多个函数当作参数,产生一个更有用的函数。
高阶函数和延迟迭代是rust的主要函数编程特性。

1
2
3
4
5
6
7
8
// Functional approach
let upper = 1000;
let sum_of_squared_odd_numbers: u32 =
(0..).map(|n| n * n) // All natural numbers squared
.take_while(|&n_squared| n_squared < upper) // Below upper limit
.filter(|&n_squared| is_odd(n_squared)) // That are odd
.fold(0, |acc, n_squared| acc + n_squared); // Sum them
println!("functional style: {}", sum_of_squared_odd_numbers);
  • 集合中的高阶函数map/find/any/every/filter/fold/take_while等等
,
© 2023 PLAYAROUND All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero