当前位置: 首页 > article >正文

【Rust自学】13.2. 闭包 Pt.2:闭包的类型推断和标注

13.2.0. 写在正文之前

Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。

在本章中,我们会讨论 Rust 的一些特性,这些特性与许多语言中通常称为函数式的特性相似:

  • 闭包(本文)
  • 迭代器
  • 使用闭包和迭代器改进I/O项目
  • 闭包和迭代器的性能

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
请添加图片描述

13.2.1. 闭包的类型推断

fn定义的函数不同,闭包不强制要求标注参数和返回值的类型。

函数需要强制标注是因为它是暴露给用户的显示接口的一部分,严格定义接口有助于所有人对参数和返回值的类型取得共识。

闭包并不会被用于这样的暴露接口,只会被存于变量中,使用时也不需要命名,更不会被暴露给我们代码库的用户。所以,闭包不强制要求标注参数和返回值的类型。

而且闭包通常很短小,只在狭小的上下文中工作,编译器通常能推断出类型。当然你手动标注出来也不是不可以。

看个例子:
这是使用函数定义的代码:

fn simulated_expensive_calculation(intensity: u32) -> u32 {  
    println!("calculating slowly...");  
    thread::sleep(Duration::from_secs(2));  
    intensity  
}

这是使用闭包的代码:

let expensive_closure = |num:u32| -> u32 {  
    println!("calculating slowly...");  
    thread::sleep(Duration::from_secs(2));  
    num  
};

这里使用显式标注是因为没有前后文供Rust推断类型,如果有,就不需要:

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));  
        }  
    }  
}

这里的参数num不需要显式声明类型是因为下文的调用中传进去的参数intensity的类型为u32,Rust推断出num的类型为u32

13.2.2. 函数和闭包定义的语法

这里有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  ;
  • 第一个是函数的定义,有函数名,形参名及类型和返回值类型
  • 第二个是闭包的定义,有参数和返回值的类型。这个闭包看着和函数的定义差不多。
  • 第三个同样是闭包,但是没有标注参数和返回值的类型,就得靠编译器推断了。
  • 第四个闭包跟第三个的不同之处在于没有了花括号{}。因为只有一个表达式,所以闭包的{}也可以被省略

13.2.3. 闭包的类型推断

闭包的定义最终只会为参数/返回值推断出唯一具体的类型。

看个例子:

    let example_closure = |x| x;

    let s = example_closure(String::from("hello"));
    let n = example_closure(5);

输出:

$ cargo run
   Compiling closure-example v0.1.0 (file:///projects/closure-example)
error[E0308]: mismatched types
 --> src/main.rs:5:29
  |
5 |     let n = example_closure(5);
  |             --------------- ^- help: try using a conversion method: `.to_string()`
  |             |               |
  |             |               expected `String`, found integer
  |             arguments to this function are incorrect
  |
note: expected because the closure was earlier called with an argument of type `String`
 --> src/main.rs:4:29
  |
4 |     let s = example_closure(String::from("hello"));
  |             --------------- ^^^^^^^^^^^^^^^^^^^^^ expected because this argument is of type `String`
  |             |
  |             in this closure call
note: closure parameter defined here
 --> src/main.rs:2:28
  |
2 |     let example_closure = |x| x;
  |                            ^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `closure-example` (bin "closure-example") due to 1 previous error

Rust编译器在闭包第一次被调用时发现它接收的值和输出的值都是String类型,就锁定这个闭包的参数和返回值都是String类型。所以后面又使用i32类型时就会报错。


http://www.kler.cn/a/506153.html

相关文章:

  • C#上位机通过CAN总线发送bin文件
  • YOLOv10-1.1部分代码阅读笔记-build.py
  • 50.【8】BUUCTF WEB HardSql
  • Python在DevOps中的应用:自动化CI/CD管道的实现
  • 配置AOSP下载环境
  • 电商项目-基于ElasticSearch实现商品搜索功能(三)
  • 麒麟系统WPS提示字体缺失问题
  • 力扣 查找元素的位置
  • # [游戏开发] Unity中的碰撞与触发器实现:从基础到应用
  • usb通过hdc连接鸿蒙next的常用指令
  • 判断192.168.1.0/24网络中,当前在线的ip有哪些
  • 文件上传生成pdf
  • 混币器是什么,波卡跨链交易平台
  • 河道流量在线自动监测系统:实时监控水流,保障河道管理安全
  • 阿里云轻量应用服务器全新升级,通用型实例峰值带宽高达200Mbps
  • 基于Oracle与PyQt6的电子病历多模态大模型图形化查询系统编程构建
  • 使用Go语言中的Buffer实现高性能处理字节和字符串
  • hashcat破解密码时出现signature unmatched error或者no hashes loaded的一种可能的原因
  • IP归属地为什么和定位不一致?原因解析
  • linux入门一
  • tomcat状态一直是Exited (1)
  • 【一个按钮一个LED】用STM32F030单片机实现苹果充电器的定时装置
  • Coconut:基于连续潜在空间推理,提升大语言模型推理能力的新方法
  • Dataset之COCO数据集:COCO数据集
  • jenkins-node节点配置
  • vue3+elementPlus之后台管理系统(从0到1)(day1)