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

news/2025/1/20 17:59:51/

13.2.0. 写在正文之前

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

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

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

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

13.2.1. 闭包的类型推断

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

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

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

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

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

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

这是使用闭包的代码:

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

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

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个例子:

rust"> 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. 闭包的类型推断

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

看个例子:

rust">    let example_closure = |x| x;let s = example_closure(String::from("hello"));let n = example_closure(5);

输出:

$ cargo runCompiling 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.ppmy.cn/news/1564717.html

相关文章

【C语言】_自定义类型:联合体

目录 1. 联合体类型的声明 2. 联合体的特点 3.1 成员变量共用一块内存 3.2 由于共用内存导致的相关性 4. 结构体与联合体对比 5. 联合体大小的计算 6. 联合体的应用 6.1 多类型特定属性组结构体 6.1.1 设计方案1&#xff1a;采用纯结构体 6.1.2 设计方案2&#xff1a…

2025寒假备战蓝桥杯01---朴素二分查找的学习

文章目录 1.暴力方法的引入2.暴力解法的思考 与改进3.朴素二分查找的引入4.朴素二分查找的流程5.朴素二分查找的细节6.朴素二分查找的题目 1.暴力方法的引入 对于下面的这个有序的数据元素的组合&#xff0c;我们的暴力解法就是挨个进行遍历操作&#xff0c;一直找到和我们的这…

PHP版接口调试工具(自定义GET|POST|COOKIE|HEADER|User Agent|来路Referer)

<?php // 如果是OPTIONS请求&#xff0c;直接返回 if ($_GET[act] ! ) { header(Content-Type: application/json); // 允许跨域请求 header(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Methods: GET, POST, OPTIONS); header(Access-Control-Allow-He…

SQL Server查询计划操作符——查询计划相关操作符(4)

7.3. 查询计划相关操作符 28)Declare:该操作符在查询计划中分配一个本地变量。该操作符是一个语言元素。该操作符具体如图7.2-28所示。 图 7.2-28 查询计划操作符Declare示例 29)Delete:该操作符从一个对象中删除满足其参数列中可选谓词的数据行。该操作符具体如图7.2-29…

SQL ON与WHERE区别

在 MySQL 中&#xff0c;ON 和 WHERE 都用于过滤数据&#xff0c;但它们的使用场景和作用有所不同&#xff0c;尤其是在涉及 JOIN 操作时。下面通过具体的例子来说明它们的区别。 1. ON 的作用 ON 用于指定表之间的连接条件&#xff0c;决定哪些行应该被连接在一起。它在 JOI…

【js进阶】设计模式之单例模式的几种声明方式

单例模式&#xff0c;简言之就是一个类无论实例化多少次&#xff0c;最终都是同一个对象 原生js的几个辅助方式的实现 手写forEch,map,filter Array.prototype.MyForEach function (callback) {for (let i 0; i < this.length; i) {callback(this[i], i, this);} };con…

【24】Word:小郑-准考证❗

目录 题目 准考证.docx 邮件合并-指定考生生成准考证 Word.docx 表格内容居中表格整体相较于页面居中 考试时一定要做一问保存一问❗ 题目 准考证.docx 插入→表格→将文本转换成表格→✔制表符→确定选中第一列→单击右键→在第一列的右侧插入列→布局→合并单元格&#…

考研数据结构线性表之顺序表

第二章线性表 1.1线性表的定义和基本操作 定义&#xff1a;线性表时具有\textcolor{blue}{相同数据类型}的n&#xff08;n≥0&#xff09;个数据元素的\textcolor{blue}{有限序列}&#xff0c;其中n为表长&#xff0c;当n0时线性表是一个空表。若用L命名线性表&#xff0c;则其…