• Rust开发——闭包使用示例


    闭包

    1. 闭包是可以捕获所在环境的匿名函数。闭包的定义:|参数列表| -> 返回类型 {代码段}
        |x:u8| -> u8 
        {
            let y = x +1;
             y
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 闭包是一个匿名函数。
      像下面合法定义,||是闭包的参数
    	|| 45;
        |x:u8| x + 1;
        |x:u8| -> u8 { x + 1 };
    
    • 1
    • 2
    • 3
    1. 闭包是把一个函数保存为变量,可以作为参数使用。
     let y = |x:u32| x+10;
     print!("{}\n",y(5))
    
    • 1
    • 2
    1. 可以在一个地方创建闭包,然后在另一个上下文中调用闭包来完成运算。
      在这里插入图片描述
     //如果只定义不调用,会报错
        let add = |a|{a+1};
        add(1);//推导出类型完成计算
    
    • 1
    • 2
    • 3

    如果有两次调用,则第二次推导失败

     //如果只定义不调用,会报错
        let add = |a|{a+1};
        add(1);
        add(2.0);
    
    • 1
    • 2
    • 3
    • 4
    • 闭包不要求标注参数和返回值的类型
    • 闭包通常很短小,只在狭小的上下文言中工作,编译器通常能推断出类型
    • 闭包可以手动添加类型标注
    1. 可以在定义的地方直接调用
    let str = (|x:String|x + &" world".to_string())("hello".to_string());
    print!("{}\n",str);
    
    • 1
    • 2
    1. 可以从其定义的作用域捕获值。
        let m = 5;
        let add = |a|{a+m};//这里捕获了当前环境外部m的值
        print!("{}\n",add(10));//输出15
    
    • 1
    • 2
    • 3

    闭包捕获变量关联的trait定义

    pub trait FnOnce<Args> {
        type Output;
        fn call_once(self, args: Args) -> Self::Output;
    }
    
    pub trait FnMut<Args>: FnOnce<Args> {
        fn call_mut(&mut self, args: Args) -> Self::Output;
    }
    
    pub trait Fn<Args>: FnMut<Args> {
        fn call(&self, args: Args) -> Self::Output;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • Fn:如果闭包只是对捕获变量不做修改操作,闭包捕获的是&T类型,闭包按照Fn trait方式执行,闭包可以重复多次执行。
    • FnMut:如果闭包对捕获变量有修改操作,闭包捕获的是&mut T类型,闭包按照FnMut trait方式执行,闭包可以重复多次执行
    • FnOnce:如果闭包会消耗掉捕获的变量,变量被move进闭包,闭包按照FnOnce trait方式执行,闭包只能执行一次

    7.闭包作为函数参数传递

    这样写是不可以的,因为闭包不属于任何类型,本质闭包是trait

    fn main()
    {
        let x = |y:u16| {y+10};
        add(x);
    }
    
    fn add(x : u16)
    {
        x(10);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这两种写法都可以:

    fn main()
    {
        let x = |y|{print!("{} \n",y)};
        foo_1(x);
    }
    
    fn foo_1<F : Fn(u16)>(x: F) 
    {
        x(5);
    }
    
    fn foo_2(x: impl Fn(u16))
    {
        x(10);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 返回闭包
      闭包属于trait,这意味着不能直接返回闭包。对于大部分需要返回trait的情况,可以使用实现了期望返回trait的具体类型来替代函数的返回值。但是这不能用于闭包,因为他们没有一个可返回的具体类型;例如不允许使用函数指针fn作为返回值类型。
      下面的例子编译不能通过
    fn return_closure() -> Fn(i32) -> i32 
    {
        |x| x+1
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

  • 相关阅读:
    接口自动化测试框架搭建全部过程
    20231014后台面经总结
    插入排序与希尔排序
    【软件基础】pycharm2021.3.2安装汉化和python3.10.1环境配置
    Allegro如何对器件进行等距对齐操作
    地平线旭日X3派小白上手
    MongoDB常用命令整理
    AJAX-解决回调函数地狱问题
    R语言dplyr包na_if函数把向量数值中的控制转化为缺失值NA、按照映射规则把指定内容转化为缺失值NA
    【神经网络】Dropout原理
  • 原文地址:https://blog.csdn.net/matt45m/article/details/126456195