Rust 基础(五)

news/2024/4/25 14:47:36/文章来源:https://blog.csdn.net/chinusyan/article/details/128108327

十一、函数式语言特性:迭代器和闭包

Rust的设计灵感来自于许多现有的语言和技术,其中一个重要影响是函数式编程( functional programming)。函数式风格的编程通常包括将函数作为值使用,方法是将它们传递到参数中,从其他函数返回它们,将它们赋值给变量以便稍后执行,等等。

在本章中,我们不讨论函数式编程是什么或不是什么,而是讨论Rust的一些特性,这些特性类似于许多语言中通常称为函数式的特性。
更具体地说,我们将介绍:

  • 闭包Closures,一个类似函数的构造,可以存储在变量中
  • 迭代器Iterators,一种处理一系列元素的方法
  • 如何使用闭包和迭代器来改进第12章的I/O项目
  • 闭包和迭代器的性能(剧透:它们比你想象的要快!)

因为掌握闭包和迭代器是编写地道的、快速的Rust代码的重要部分,所以我们将用整章的时间来讨论它们。

11.1 闭包:捕获其环境的匿名函数

Rust的闭包是匿名函数,可以保存在变量中,也可以作为参数传递给其他函数。您可以在一个地方创建闭包,然后在其他地方调用闭包,以在不同的上下文中计算它。与函数不同,闭包可以从定义它们的作用域捕获值。我们将演示这些闭包特性如何支持代码重用和行为我自定义。

11.1.1 使用闭包捕获环境

我们将首先研究如何使用闭包从定义闭包的环境中捕获值,以供以后使用。场景是这样的:每隔一段时间,我们的t恤公司就会向我们邮件列表上的某个人赠送一件独家限量版衬衫作为促销。邮件列表上的用户可以选择将自己喜欢的颜色添加到个人资料中。如果被选为免费衬衫的人有他们最喜欢的颜色,他们就会得到那种颜色的衬衫。如果这个人没有指定最喜欢的颜色,他们就得到公司目前最多的颜色。

有许多方法可以实现这一点。对于本例,我们将使用一个名为ShirtColor的枚举,它具有变体RedBlue(为简单起见,限制了可用颜色的数量)。我们用一个inventory结构体表示公司的库存,该结构体有一个名为shirts的字段,该字段包含Vec<ShirtColor>,表示当前库存的衬衫颜色。在Inventory中定义的方法giveaway获得免费衬衫获胜者的可选衬衫颜色偏好,并返回该人将获得的衬衫颜色。这个设置如清单13-1所示:

#[derive(Debug, PartialEq, Copy, Clone)]
enum ShirtColor {Red,Blue,
}struct Inventory {shirts: Vec<ShirtColor>,
}impl Inventory {fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {user_preference.unwrap_or_else(|| self.most_stocked())}fn most_stocked(&self) -> ShirtColor {let mut num_red = 0;let mut num_blue = 0;for color in &self.shirts {match color {ShirtColor::Red => num_red += 1,ShirtColor::Blue => num_blue += 1,}}if num_red > num_blue {ShirtColor::Red} else {ShirtColor::Blue}}
}fn main() {let store = Inventory {shirts: vec![ShirtColor::Blue, ShirtColor::Red, ShirtColor::Blue],};let user_pref1 = Some(ShirtColor::Red);let giveaway1 = store.giveaway(user_pref1);println!("The user with preference {:?} gets {:?}",user_pref1, giveaway1);let user_pref2 = None;let giveaway2 = store.giveaway(user_pref2);println!("The user with preference {:?} gets {:?}",user_pref2, giveaway2);
}

main定义的store 有两件蓝色衬衫和一件红色衬衫,以分发本次限量版促销。对于一个喜欢穿红衬衫的用户和一个不喜欢穿红衬衫的用户,我们调用giveaway 方法。

同样,这段代码可以通过多种方式实现,在这里,为了关注闭包,除了giveaway 使用闭包的方法之外,我们一直坚持您已经学过的概念。在giveaway 方法中,我们获得用户首选项作为类型Option<ShirtColor>并在user_preference上调用unwrap_or_else方法(Option<T>由标准库定义)。它有一个参数:一个没有任何参数的闭包,返回值T(与Option<T>的Some变体中存储的类型相同,在本例中是ShirtColor)。如果Option<T>是Some变量,unwrap_or_else从Some变量中返回值。如果Option<T>是None变量,unwrap_or_else调用闭包并返回由闭包返回的值。

我们指定闭包表达式|| self. most_stored()作为unwrap_or_else的参数。这是一个闭包,它本身没有参数(如果闭包有参数,它们将出现在两个竖线之间)。闭包的主体调用self. most_stocking()。我们在这里定义闭包,如果需要结果,unwrap_or_else的实现稍后将计算闭包。

Running this code prints:

$ cargo runCompiling shirt-company v0.1.0 (file:///projects/shirt-company)Finished dev [unoptimized + debuginfo] target(s) in 0.27sRunning `target/debug/shirt-company`
The user with preference Some(Red) gets Red
The user with preference None gets Blue

这里一个有趣的方面是,我们在当前Inventory实例上传递了一个调用self. most_stocking()的闭包。标准库不需要知道我们定义的InventoryShirtColor类型的任何信息,也不需要知道我们想在这个场景中使用的逻辑。闭包捕获对self Inventory实例的不可变引用,并将其与我们指定的代码一起传递给unwrap_or_else方法。另一方面,函数不能以这种方式捕获它们的环境。

11.1.1 闭包类型推断和注释

函数和闭包之间有更多的区别。闭包通常不需要像fn函数那样注释形参或返回值的类型。函数上需要类型注释,因为类型是向用户公开的显式接口的一部分。严格定义这个接口对于确保所有人都同意函数使用和返回的值类型非常重要。另一方面,闭包不会在这样的公开接口中使用:它们存储在变量中,在使用时不给它们命名,也不向库的用户公开它们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_39049.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】No.103. Binary Tree Zigzag Level Order Traversal -- Java Version

题目链接&#xff1a;https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ 1. 题目介绍&#xff08;Binary Tree Zigzag Level Order Traversal&#xff09; Given the root of a binary tree, return the zigzag level order traversal of its nodes’…

【学习笔记67】JavaScript中的闭包

一、认识函数的过程 1. 定义 在堆内存中开辟一段内存空间(XF001)把函数体的内容&#xff0c;完全百分百的照抄一份&#xff0c;存放在内存空间中(XF001)把内存空间的地址(XF001) 赋值给函数名2. 调用 根据函数名内存储的地址 (XF001) &#xff0c;去堆内存中找到对应函数会去…

R语言法国足球联赛球员多重对应分析(MCA)

数据集 fooball球员在场上的位置 数据来自国际足联的视频游戏FIFA 。游戏的特点是在游戏的各个方面评价每个球员的能力。等级是量化变量&#xff08;介于0和100之间&#xff09;&#xff0c;但我们将它们转换为分类变量。所有能力都被编码在4个等级&#xff1a;1.低/ 2.平均/ …

基于单片机技术的自动停车器的设计

目 录 摘 要 I Abstract II 1绪论 1 1.1课题研究背景 1 1.2国内外发展现状 1 1.3汽车自动停车器的研究目的 2 1.4课题研究的意义 2 2汽车停车器的功能设计 3 2.1汽车自动停车器的设计要求 3 2.2停车器的主要功能 3 3汽车自动停车器的硬件设计 5 3.1汽车自动停车器的硬件组成 5 …

数据存储——存储视频

数据存储——存储视频视频的数字化一、视频采样二、视频量化总结&#xff1a;视频数字化的过程视频的数字化 1.视频是图像&#xff08;帧&#xff09;在时间上的表示 图象是离散的视频&#xff0c;视频是连续的图像 2.视频储存 每一帧图像或帧被转化为位模式并加以储存 一、视…

三年城市NOH落地100城,毫末智行内部信剑指2025

11月29日&#xff0c;毫末智行董事长张凯、CEO顾维灏联合发布《毫末智行三周岁&#xff1a;三年磨一剑 利刃开新篇》的内部信&#xff0c;提到毫末愿景及战略目标&#xff1a;“让机器智能移动&#xff0c;给生活更多美好。”未来成长为一家产品矩阵覆盖全无人驾驶、机器人等多…

【Android App】Vulkan实现宇宙中旋转雷达动画效果(附源码和原始视频 超详细必看)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、Vulkan简介 Vulkan是一个跨平台的图形绘制接口&#xff0c;被称为下一代OpenGL&#xff0c;因为尽管OpenGL提供了丰富的图形API&#xff0c;但他在底层实现的C代码早已封装起来&#xff0c;由于开发者修改不了底层代码&#xf…

​GENIUS: 根据草稿进行文本生成的预训练模型,可用于多种NLP任务的数据增强...

©PaperWeekly 原创 作者 | 郭必扬 单位 | 上海财经大学信息管理与工程学院AI Lab论文标题&#xff1a;GENIUS: Sketch-based Language Model Pre-training via Extreme and Selective Masking for Text Generation and Augmentation论文作者&#xff1a;Biyang Guo, Yeyu…

多线程,了解-概念-实现方式-常见方法-安全问题-死锁-生产者消费者

了解 简单了解多线程 是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程&#xff0c;提升性能。 简单了解多线程 简单了解多线程 简单了解多线程 简单了解多线程 概念 线程相关的概念 并行&#xff1a;在同…

【车载开发系列】UDS诊断---电控单元复位 ($0x11)

【车载开发系列】UDS诊断—电控单元复位&#xff08;$0x11&#xff09; UDS诊断---电控单元复位&#xff08;$0x11&#xff09;【车载开发系列】UDS诊断---电控单元复位&#xff08;$0x11&#xff09;一.概念定义二.应用场景三.报文格式1&#xff09;请求2&#xff09;肯定响应…

Spark 3.0 - 8.ML Pipeline 之决策树原理与实战

目录 一.引言 二.决策树基础-信息熵 三.决策树的算法基础 - ID3 算法 四.ML 中决策树的构建 1.信息增益计算 2.连续属性划分 五.ML 决策树实战 1.Libsvm 数据与加载 2.StringIndexer 3.VectorIndexer 4.构建决策树与 Pipeline 5.测试与评估 6.获取决策树 六.总结…

基于PHP+MySQL企业网络推广平台系统的设计与实现

企业网络推广平台系统具有很强的信息指导性特征,采用PHP开发企业网络推广平台系统 给web带来了全新的动态效果,具有更加灵活和方便的交互性。在Internet中实现数据检索越来越容易,可以及时、全面地收集、存储大量的企业资源信息以及进行发布、浏览、搜索相关的信息。让企业、个…

C++ Reference: Standard C++ Library reference: Containers: list: list: cend

C官网参考链接&#xff1a;https://cplusplus.com/reference/list/list/cend/ 公有成员函数 <list> std::list::cend const_iterator cend() const noexcept; 返回结束的常量迭代器 返回一个指向容器结束后元素的const_iterator。 const_iterator是指向const内容的迭代…

Spring Boot FailureAnalyzer 应用场景

Spring Boot 自定义FailureAnalyzer 今天在学习Spring Boot 源码的过程中&#xff0c;在spring.factories 文件中无意中发现了FailureAnalyzer 这个接口。由于之前没有接触过&#xff0c;今天来学习一下 FailureAnalyzer 接口的作用。 在学习FailureAnalyzer之前, 我们先看以…

TMA三均线股票期货高频交易策略的R语言实现

趋势交易策略是至今应用最广泛以及最重要的投资策略之一&#xff0c;它的研究手段种类繁多&#xff0c;所运用的分析工具也纷繁复杂&#xff0c;其特长在于捕捉市场运动的大方向。股指期货市场瞬息万变&#xff0c;结合趋势分析方法&#xff0c;量化投资策略能够得到更有效的应…

Discourse 的左侧边栏可以修改吗

在默认的 Discourse 配置中&#xff0c;我们左侧的边栏可以根据自己的要求进行修改吗&#xff1f; 解决办法 针对自己登录的用户&#xff0c;你是可以自己调整左侧边栏的配置。 单击右上角你的个人头像&#xff0c;然后选择属性。 在切换的界面中&#xff0c;选择属性。 在出…

校园论坛(Java)——环境配置篇

校园论坛&#xff08;Java&#xff09;——环境配置篇 文章目录校园论坛&#xff08;Java&#xff09;——环境配置篇1、写在前面2、新建Maven项目2.1 引入相关依赖2.2 配置Tomcat环境3、项目发布测试4、项目代码5、参考资料1、写在前面 Windows版本&#xff1a;Windows10JDK版…

Python数据库编程之关系数据库API规范

Python关系数据库API规范 对于关系数据库的访问&#xff0c;Python社区已经制定出一个标准&#xff0c;称为Python Database API Specification。Mysql&#xff0c;Oracal等特定数据库模块遵从这一规范&#xff0c;而且可以添加更多特性。 高级数据库API定义了一组用于连接数…

YOLO V3 详解

YOLO V3 论文链接&#xff1a;YOLOv3: An Incremental Improvement 主要改进 Anchor: 9个大小的anchor&#xff0c;每个尺度分配3个anchor。Backbone改为Darknet-53, 引入了残差模块。引入了FPN&#xff0c;可以进行多个尺度的训练&#xff0c;同时对于小目标的检测有了一定…