闭包 Closure

定义

闭包是一种匿名函数,它可以

  • 将函数赋值给变量
  • 作为参数传递给其它函数
  • 允许捕获调用者作用域中的值
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)
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值