定义
闭包是一种匿名函数,它可以
- 将函数赋值给变量
- 作为参数传递给其它函数
- 允许捕获调用者作用域中的值
fn main() {
let x = 1;
let sum = |y| x + y;
assert_eq!(3, sum(2));
}
语法
|param1, param2,...| -> 返回值类型{
语句1;
语句2;
返回表达式
}
// example
let sum = |x: i32, y: i32| -> i32 {
x + y
}
// 只有一个返回表达式,省略大括号
|param1| 返回表达式
// example
let sum = |x, y| x + y;
// 没有参数
|| 返回表达式
// example
let action = || {
// 外部变量
x
};
//结构体中的闭包
struct Cacher<T>
where
T: Fn(u32) -> u32,
{
query: T,
value: Option<u32>,
}
闭包捕获作用域中的值
Fn三种特征:
- FnOnce 该类型的闭包会拿走被捕获变量的所有权。该闭包只能运行一次。
- FnMut
- Fn
fn fn_once<F>(func: F)
where
F: FnOnce(usize) -> bool,
{
println!("{}", func(3));
println!("{}", func(4));//仅实现 FnOnce 特征的闭包在调用时会转移所有权,所以显然不能对已失去所有权的闭包变量进行二次调用:
}
fn main() {
let x = vec![1, 2, 3];
fn_once(|z|{z == x.len()})
}
fn fn_once<F>(func: F)
where
F: FnOnce(usize) -> bool + Copy,// 改动在这里
{
println!("{}", func(3));
println!("{}", func(4));//通过添加Copy trait, 不转移所有权
}
fn main() {
let x = vec![1, 2, 3];
fn_once(|z|{z == x.len()})
}
fn main() {
let mut s = String::new();
// 不可变借用
//let update_string = |str| s.push_str(str);
let mut update_string = |str| s.push_str(str);
exec(update_string);
println!("{:?}",s);
}
// FnMut是推导出的特征类型,mut是rust语言层面的一个修饰符
fn exec<'a, F: FnMut(&'a str)>(mut f: F) {
f("hello")
}
fn main() {
// s为不可变借用
let s = "hello, ".to_string();
let update_string = |str| println!("{},{}",s,str);
exec(update_string);
println!("{:?}",s);
}
// Fn 不可变借用
fn exec<'a, F: Fn(String) -> ()>(f: F) {
f("world".to_string())
}
Fn规则
- 所有的闭包都自动实现了
FnOnce
特征,因此任何一个闭包都至少可以被调用一次 - 没有移出所捕获变量的所有权的闭包自动实现了
FnMut
特征 - 不需要对捕获变量进行改变的闭包自动实现了
Fn
特征
fn main() {
let s = String::new();
let update_string = || println!("{}",s);
exec(update_string);
exec1(update_string);
exec2(update_string);
}
fn exec<F: FnOnce()>(f: F) {
f()
}
fn exec1<F: FnMut()>(mut f: F) {
f()
}
fn exec2<F: Fn()>(f: F) {
f()
}
闭包作为函数返回值
用特征对象 Box
的方式实现
fn factory(x:i32) -> Box<dyn Fn(i32) -> i32> {
let num = 5;
if x > 1{
Box::new(move |x| x + num)
} else {
Box::new(move |x| x - num)
}
}