Rust 的 闭包(closures)是可以保存进变量或作为参数传递给其他函数的匿名函数。可以在一个地方创建闭包,然后在不同的上下文中执行闭包运算。不同于函数,闭包允许捕获调用者作用域中的值。我们将展示闭包的这些功能如何复用代码和自定义行为。
定义一个闭包
1 2 3 4 5
| let expensive_closure = |num| { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num };
|
官方例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| use std::thread; use std::time::Duration;
fn main() { generate_workout(25, 43); }
fn generate_workout(intensity: u32, random_number: u32) { let expensive_closure = |num| { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num };
if intensity < 25 { println!("Today, do {} pushups!", expensive_closure(intensity)); println!("Next, do {} situps!", expensive_closure(intensity)); } else { if random_number == 3 { println!("Take a break today! Remember to stay hydrated!"); } else { println!("Today, run for {} minutes!", expensive_closure(intensity)); } } }
|
闭包类型推断和注解
在’|’符号中添加闭包参数的类型和 ‘{‘ 前添加返回值增加类型。这类似与函数中的类型注解。
1 2 3 4 5
| let expensive_closure = |num: u32| -> u32 { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num };
|
几个行为相同的闭包:
1 2 3 4
| fn add_one_v1 (x: u32) -> u32 { x + 1 } let add_one_v2 = |x: u32| -> u32 { x + 1 }; let add_one_v3 = |x| { x + 1 }; let add_one_v4 = |x| x + 1 ;
|
带有泛型和 Fn trait 的闭包
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| use std::thread; use std::time::Duration;
struct Cacher<T> where T: Fn(u32) -> u32, { calculation: T, value: Option<u32>, }
impl<T> Cacher<T> where T: Fn(u32) -> u32, { fn new(calculation: T) -> Cacher<T> { Cacher { calculation, value: None, } }
fn value(&mut self, arg: u32) -> u32 { match self.value { Some(v) => { if v == arg { v } else { let v = (self.calculation)(arg); self.value = Some(v); v } } None => { let v = (self.calculation)(arg); self.value = Some(v); v } } } }
fn main() { let mut expensive_result = Cacher::new(|num| { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num });
println!("{}", expensive_result.value(13)); println!("{}", expensive_result.value(13)); println!("{}", expensive_result.value(13)); println!("{}", expensive_result.value(13)); println!("{}", expensive_result.value(3)); println!("{}", expensive_result.value(3)); println!("{}", expensive_result.value(3)); }
fn generate_workout(intensity: u32, random_number: u32) { let mut expensive_result = Cacher::new(|num| { println!("calculating slowly..."); thread::sleep(Duration::from_secs(2)); num });
if intensity < 25 { println!("Today, do {} pushups!", expensive_result.value(intensity)); println!("Next, do {} situps!", expensive_result.value(intensity)); } else { if random_number == 3 { println!("Take a break today! Remember to stay hydrated!"); } else { println!( "Today, run for {} minutes!", expensive_result.value(intensity) ); } } }
|