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

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

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); | --------------- ^ 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; | ^ help: try using a conversion method | 5 | let n = example_closure(5.to_string()); | ++++++++++++ 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.jsqmd.com/news/1249545/

相关文章:

  • 三星 Galaxy Z Fold 8 Ultra 开启预购,可视性、耐用性、性能全面升级!
  • 重构建材获客逻辑:建材企业携手西安信之上,解锁 GEO 推广增长新通路
  • 2026 年下半年!肉牛后期冲刺靠谱产品推荐,出栏增重正规品牌深度解析 - 优企甄选
  • 威联通NAS部署openwrt软路由保姆级教程附镜像文件
  • AI驱动的课程论文写作工具:书匠策AI全解析
  • 【Python毕业设计】基于 Python 的校园闲置资源互动流转交易系统设计与实现 带互动交流功能的校园二手交易平台设计(源码+文档+远程调试,全bao定制等)
  • 2026年7月美的空调售后服务电话人工客服400受理热线升级公告 - AAA家电服务指南
  • 抖店一件代发物流单号怎么回传?新手发货软件操作步骤分享 - 电商分享
  • 2026年7月最新无锡市滨湖区亨得利名表服务中心电话公示 - 亨得利官方博客
  • RNN训练中的梯度问题与梯度裁剪实战解析
  • 2026年如何系统的入门大模型?
  • 【Rust自学】13.1. 闭包 Pt.1:什么是闭包、如何使用闭包
  • 超详细:Dify大语言模型工作流开发平台的安装与使用,deepseek知识库客服等
  • 基于MATLAB图像处理与神经网络的肺癌智能分类系统
  • 全文 - APB3
  • 禹州龙悦府首选装修设计公司推荐 - 猜不透的vv
  • [AG-UI详解-05]如何构建一个兼容AG-UI协议的客户端
  • V2G微电网多目标优化调度与改进灰狼算法研究
  • 惠州发电机回收推荐:2026严选评本土老牌高口碑推荐 - 广东再生资源回收
  • 【Rust自学】2.3. 猜数游戏Pt.3 输入数与随机数的对比
  • 宝玑苏州网点地址及售后服务热线电话2026年7月权威通告 - 亨得利官方服务中心
  • INT4 通俗完整讲解
  • 杭州管道疏通哪家靠谱?2026西湖区业主真实测评避坑指南 - 余生黄金回收
  • 智能体、AIGC与AGI:核心技术差异与应用解析
  • 2026年7月最新宝玑扬州江都吾悦广场维修保养服务电话 - 亨得利钟表维修中心
  • MCU FLASH读写的简单分析
  • DSP/BIOS内存优化实战:模块化裁剪与配置策略详解
  • 专科生论文写作AI工具对比:千笔与Checkjie实测分析
  • FlexRay通信控制器中断寄存器配置与应用实战指南
  • 全球首创!Seedacn2.5首款支持专业3D工作流的AI视频工具 - 企业新闻快传