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

【Rust自学】13.4. 闭包 Pt.4:使用闭包捕获环境

13.4.0. 写在正文之前

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

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

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

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

13.4.1. 闭包可以捕获它所在的环境

闭包有一项函数所不具备的功能:闭包可以访问定义它的作用域内的变量。

看个例子:

fn main() {let x = 4;let equal_to_x = |z| z == x;let y = 4;assert!(equal_to_x(y));
}

闭包的部分在:

let equal_to_x = |z| z == x;

这样写有的人可能不太能分清===在这里的作用,换一种写法:

let equal_to_x = |z| {z == x;
}

也就是说这个闭包的形参是z,它会和x(也就是4,因为上文定义了x = 4)进行比较,返回布尔类型,如果相等就是true,反之则为false

这里闭包直接访问了同在一个作用域的变量x,这是函数做不到的。

但使用这个特性是有代价的,它会产生内存开销。大多数情况下我们不需要它捕获环境,更不想产生内存开销,所以函数它就不允许从环境中捕获变量,而定义和使用函数就永远不会产生这一类型的开销。

13.4.2. 闭包从所在环境捕获值的方式

闭包通过三种方法来从环境捕获值,这三种与函数获得参数的三种方法一样:

  • 取得所有权,其trait名为FnOnceOnce代表一次,因为闭包不能多次获取并消耗同一个变量,所以它只能被调用一次。
  • 可变借用,其trait名为FnMut
  • 不可变借用,其trait名为Fn

当程序员在创建闭包时,通过闭包对环境值当使用,Rust会推断出具体使用哪个trait:

  • 所有的闭包都实现了FnOnce,因为闭包都至少可以被调用一次
  • 没有移动捕获变量的实现了FnMut
  • 无需可变访问捕获变量的闭包实现了Fn

实际上这三者有包含关系:所有实现了Fn的都实现了FnMut,所有实现了FnMut的都实现了FnOnce

13.4.3. move关键字

在参数列表前使用move关键字,可以强制闭包取得它所使用的环境值的所有权。当将闭包传递给新线程以移动数据使其归新线程所有时,此方法最为有用。

看个例子:

fn main() {let x = vec![1, 2, 3];let equal_to_x = move |z| z == x;println!("can't use x here {:?}", x);let y = vec![1, 2, 3];assert!(equal_to_x(y));
}

使用了move关键字后x的所有权就移动到了闭包的里面,后面就用不了x

13.4.4. 最佳实践

当你指定Fn trait bound之一时,首先用Fn,基于闭包内的情况,如果需要FnOnceFnMut,编译器会再告诉你。

http://www.lryc.cn/news/522475.html

相关文章:

  • 在 macOS 上,用命令行连接 MySQL(/usr/local/mysql/bin/mysql -u root -p)
  • mono3d汇总
  • K8S 节点选择器
  • 【2024年华为OD机试】 (C卷,200分)- 反射计数(Java JS PythonC/C++)
  • AI编程工具使用技巧——通义灵码
  • 挖掘机检测数据集,准确识别率91.0%,4327张原始图片,支持YOLO,COCO JSON,PASICAL VOC XML等多种格式标注
  • 使用Docker部署postgresql
  • LabVIEW时域近场天线测试
  • LabVIEW桥接传感器数据采集与校准程序
  • 菜品管理(day03)
  • 深入理解 Android 混淆规则
  • 《Keras 3 在 TPU 上的肺炎分类》
  • 从 Android 进行永久删除照片恢复的 5 种方法
  • SDL2:Android APP编译使用
  • linux systemd 服务连续启动失败,不会再重启分析
  • 【云岚到家】-day03-门户缓存方案选择
  • 在IDEA中使用通义灵码插件:全面提升开发效率的智能助手
  • 【正则表达式】从0开始学习正则表达式
  • PHP智慧小区物业管理小程序
  • Linux安装Docker教程(详解)
  • 开源AI微调指南:入门级简单训练,初探AI之路
  • Leetcode 91. 解码方法 动态规划
  • ASP .NET Core 学习(.NET9)配置接口访问路由
  • 将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(2 换掉付费的Event Hubs)
  • idea 如何安装 github copilot
  • 1.17学习
  • Redis系列之底层数据结构整数集IntSet
  • 外包公司名单一览表(成都)
  • 个人vue3-学习笔记
  • STM32 FreeRTOS消息队列