• Rust函数进阶


    Rust系列:初步所有权结构体和枚举类

    函数

    先来回顾一下Rust中函数的创建过程,在Rust中,函数用fn声明,如有传入参数或返回值,都需要声明数据类型,下面是一个质朴的阶乘函数

    可以写一个阶乘函数

    fn fac(x:i32)->i32{
        if x>1{
            return x*fac(x-1);
        }else{
            return 1;
        }
    }
    
    fn main(){
        let x = fac(5);
        println!("5!={}",x);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试为

    >rustc main.rs
    >main.exe
    5!=120
    
    • 1
    • 2
    • 3

    函数中的函数

    Rust中的函数并不支持传入任意参数,如果非要这么干,那么需要用宏来假装实现,故而就等到介绍宏的时候再说。

    但Rust提供了一些函数式特性,首先支持在函数中再定义一个函数,示例如下

    //lambda.rs
    fn closure_test_1(){
        fn add(a:i32, b:i32) -> i32 {a + b}
        println!("3+4={}", add(3,4));
    }
    fn main(){
        closure_test_1();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试结果如下

    >rustc lambda.rs
    >lambda.exe
    3+4=7
    
    • 1
    • 2
    • 3

    lambda表达式

    函数式编程的一大优势就是把函数当作变量,那么既然是变量,就应该可以用let绑定,而想用let绑定,就必须通过赋值好把函数名和函数内容分开,这就是lambda表达式

    Rust中的lambda表达式,从写法上来说,就是用两个竖线代替函数的括号,总共有四种写法,示例如下

    fn closure_test_2(){
        let add = |a:f32, b:f32| -> f32{a+b};
        let minus = |a,b| {a-b};
        let mul = |a, b| a*b;
        let div = move |a,b| a/b;
    
        println!("add(3,4)={}", add(3.0,4.0));
        println!("minus(3,4){}", minus(3.0,4.0));
        println!("mul(3,4)={}", mul(3.0,4.0));
        println!("div(3,4)={}", div(3.0,4.0));
    }
    fn main(){
        closure_test_2();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    其中,add是比较完整的写法;minus则是简化版本,并且开启了类型判断;mul进一步简化,省略了花括号;div则使用了move关键字,其功能是强制闭包取得被捕获变量的所有权。

    运行结果如下

    add(3,4)=7
    minus(3,4)-1
    mul(3,4)=12
    div(3,4)=0.75
    
    • 1
    • 2
    • 3
    • 4

    函数作为参数

    为了明白我们要干什么,下面举一个最简单的示例,新建一个fun_test,这个函数有三个参数,前两个参数是整数,第三个参数是一个可以调用两个参数的函数,示例如下

    fn fun_test(v1: i32, v2: i32,  
        f: &dyn Fn(i32, i32) -> i32){
        println!("{}", f(v1, v2));
    }
    
    fn main() {
        let mul = |a, b| a*b;
        println!("5x8=");
        fun_test(5, 8, &mul);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    上述代码有个值得注意的地方,首先fun_test第三个参数的类型为&dyn Fn(i32, i32)->i32,即这是个Fn类型的函数,并且用到了取地址符&,并且用到了trait前缀dyn。相应地,在调用fun_test时,其传入参数mul也用到了取地址符。

    测试结果如下

    >lambda.exe
    5x8=40
    
    • 1
    • 2

    Rust中提供了三种作为参数的函数类型,其限制如下

    • Fn:不能修改捕获的对象。
    • FnMut:可以修改捕获的对象。
    • FnOnce:只能调用一次
  • 相关阅读:
    学个Antenna:Matlab天线工具箱知多少(二)
    docker搭建yapi接口文档系统、Idea中上传接口、在线调用
    2023黑龙江八一农垦大学计算机考研信息汇总
    Linux将程序放到后台运行
    【Redis】Redis-cli命令行工具解析与应用(Redis专栏启动)
    【js】vue获取document.getElementById(a)为null
    在 KubeSphere 部署 Wiki 系统 wiki.js 并启用中文全文检索
    SpringBoot 使用 Minio 进行文件存储
    最短Hamilton路径( 二进制 + 状态压缩dp)
    策略模式调优(多Oss存储导致代码冗余的问题)
  • 原文地址:https://blog.csdn.net/m0_37816922/article/details/133849056