Rust- 闭包
A closure in Rust is an anonymous function you can save in a variable or pass as an argument to another function. You can create the closure using a lightweight syntax and access variables from the scope in which it’s defined.
Here’s an example of a closure that increases a number by one:
let plus_one = |x: i32| x + 1;let a = 5;
println!("{}", plus_one(a)); // Outputs 6
In this example, plus_one
is a closure that takes one argument x
and returns x + 1
.
Closures in Rust are similar to lambdas in other languages, but they have some specific behaviors and capabilities.
-
Capture Environment: Closures have the ability to capture values from the scope in which they’re defined. Here’s an example:
let num = 5; let plus_num = |x: i32| x + num; println!("{}", plus_num(10)); // Outputs 15
Here,
plus_num
captures the value ofnum
from the surrounding environment. -
Flexible Input Types: Unlike functions, closures don’t require you to annotate the types of the input parameters. However, you can if you want to, and sometimes doing so can increase clarity.
-
Three Flavors of Closures: Closures in Rust come in three forms, which differ in how they capture variables from the surrounding scope:
Fn
,FnMut
, andFnOnce
. The type is chosen by the compiler based on how the closure uses variables from the environment.FnOnce
consumes the variables it captures from its enclosing scope, known as the “once” because it can’t take ownership more than once.FnMut
can change the environment because it mutably borrows values.Fn
borrows values from the environment immutably.
Let’s start with an overview of each:
-
FnOnce captures variables and moves them into the closure when it is defined. It can consume those variables when the closure is called. FnOnce closures can’t be called more than once in some contexts without duplication.
-
FnMut can mutate and also consume variables from the environment in which it is defined.
-
Fn borrows variables from the environment immutably.
Now, let’s have a look at some examples for each type:
// Example of FnOnce
let x = "hello".to_string();
let consume_x = move || println!("{}", x);
consume_x(); // "hello"
// consume_x(); This won't compile because `x` has been moved into the closure// Example of FnMut
let mut y = "hello".to_string();
let mut append_world = || y.push_str(" world");
append_world();
println!("{}", y); // "hello world"// Example of Fn
let z = "hello".to_string();
let print_z = || println!("{}", z);
print_z();
print_z(); // We can call this as many times as we want.
① In the first example, the closure takes ownership of x
(indicated by the move
keyword), so it’s a FnOnce
.
② In the second example, the closure mutably borrows y
, so it’s a FnMut
.
③ In the third example, the closure immutably borrows z
, so it’s a Fn
.
Rust chooses how to capture variables on the fly without any annotation required. The move
keyword is used to force the closure to take ownership of the values it uses.
Closures are a fundamental feature for many Rust idioms. They are used extensively in iterator adapters, threading, and many other situations.
fn main() {/*|| 代替 ()将输入参数括起来函数体界定符是{},对于单个表达式是可选的,其他情况必须加上。有能力捕获外部环境的变量。|参数列表| {业务逻辑}|| {业务逻辑}闭包可以赋值一个变量。*/let double = |x| {x * 2};let add = |a, b| {a + b};let x = add(2, 4);println!("{}", x); // 6let y = double(5);println!("{}", y); // 10let v = 3;let add2 = |x| {v + x};println!("{}", add2(4)); // 7/*闭包,可以在没有标注的情况下运行。可移动(move), 可借用(borrow), 闭包可以通过引用 &T可变引用 &mut T值 T捕获1. 闭包是一个在函数内创建立即调用的另外一个函数。2. 闭包是一个匿名函数3. 闭包虽然没有函数名,但可以把整个闭包赋值一个变量,通过该变量来完成闭包的调用4. 闭包不用声明返回值,但可以有返回值。并且使用最后一条语句的执行结果作为返回值,闭包的返回值也可以给变量。5. 闭包也称之为内联函数,可以访问外层函数里的变量。*/
}
fn main() {let add = |x, y| x + y;let result = add(3, 4);println!("{}", result); // 7receives_closure(add); // // 闭包作为参数执行结果 => 8let y = 2;receives_closure2(|x| x + y); // closure(1) => 3let y = 3;receives_closure2(|x| x + y); // closure(1) => 4let closure = returns_closure();println!("返回闭包 => {}", closure(1)); // 返回闭包 => 7let result = do1(add, 5);println!("result(1) => {}", result(1)); // result(1) => 6let result = do2(add, 5);println!("result(2) => {}", result(2)); // result(2) => 7
}fn do2<F, X, Y, Z>(f: F, x: X) -> impl Fn(Y) -> Z
whereF: Fn(X, Y) -> Z,X: Copy,
{move |y| f(x, y)
}// 参数和返回值都有闭包
fn do1<F>(f: F, x: i32) -> impl Fn(i32) -> i32
whereF: Fn(i32, i32) -> i32,
{move |y| f(x, y)
}// 返回闭包
fn returns_closure() -> impl Fn(i32) -> i32 {|x| x + 6
}// 闭包作为参数
fn receives_closure<F>(closure: F)
whereF: Fn(i32, i32) -> i32,
{let result = closure(3, 5);println!("闭包作为参数执行结果 => {}", result)
}// 闭包捕获变量
fn receives_closure2<F>(closure: F)
whereF: Fn(i32) -> i32,
{let result = closure(1);println!("closure(1) => {}", result);
}
相关文章:
Rust- 闭包
A closure in Rust is an anonymous function you can save in a variable or pass as an argument to another function. You can create the closure using a lightweight syntax and access variables from the scope in which it’s defined. Here’s an example of a clo…...

【数据挖掘torch】 基于LSTM电力系统负荷预测分析(Python代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
「JVM」性能调优工具
「JVM」性能调优工具 一、jcmd1、jcmd 能干嘛?2、与JVM相关的命令3、示例 二、jmap1、jmap有什么用?2、jmap的命令大全3、示例 三、jps1、jps有什么用?2、jps命令以及示例 四、jstat1、jstat有什么用?2、jstat命令以及示例 五、js…...

IDEA Debug小技巧 添加减少所查看变量、查看不同线程
问题 IDEA的Debug肯定都用过。它下面显示的变量,有什么门道?可以增加变量、查看线程吗? 答案是:可以。 演示代码 代码如下: package cn.itcast.attempt.threadAttempt.attempt2;public class Test {public static …...

基于SpringBoot+Vue的车辆充电桩管理系统设计与实现(源码+LW+部署文档等)
博主介绍: 大家好,我是一名在Java圈混迹十余年的程序员,精通Java编程语言,同时也熟练掌握微信小程序、Python和Android等技术,能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…...

Bean的加载方式
目录 1. 基于XML配置文件 2. 基于XML注解方式声明bean 自定义bean 第三方bean 3.注解方式声明配置类 扩展1,FactoryBean 扩展2,加载配置类并加载配置文件(系统迁移) 扩展3,proxyBeanMethodstrue的使用 4. 使用Import注解导入要注入的bean…...

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(13)-Fiddler请求和响应断点调试
1.简介 Fiddler有个强大的功能,可以修改发送到服务器的数据包,但是修改前需要拦截,即设置断点。设置断点后,开始拦截接下来所有网页,直到取消断点。这个功能可以在数据包发送之前,修改请求参数;…...

Android 13(T) - Media框架(1)- 总览
从事Android Media开发工作三年有余,刚从萌新变成菜鸟,一路上跌跌撞撞学习,看了很多零零碎碎的知识,为了加深对Android Media框架的理解,决定在这里记录下学习过程中想到的一些问题以及一些思考,也希望对初…...
简述vue3(ts)+antdesignvue项目框架搭建基本步骤
目录 项目简介 概念 过程简述 基本步骤 1.创建新项目 2.安装Ant Design Vue 3.配置Ant Design Vue 4.创建页面和组件 5.使用组件 6.运行项目 项目简介 概念 Vue 3(使用TypeScript)和Ant Design Vue项目框架搭建是指在Vue 3框架下,…...
webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1
webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1 1.问题2. 解决办法: 1.问题 使用webpack打包是报错如下: webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1,因为在此系统上禁止运行脚本。有关详细信息,…...
GDAL OGR C++ API 学习之路 (5)OGRLayer篇 代码示例
GetStyleTable virtual OGRStyleTable *GetStyleTable () 返回图层样式表 返回: 指向不应由调用方修改或释放的样式表的指针 // 假设图层对象为 poLayer OGRStyleTable* poStyleTable poLayer->GetStyleTable(); if (poStyleTable ! nullptr) {// 处理样式表信息// ..…...

NIDEC COMPONENTS尼得科科宝滑动型DIP开关各系列介绍
今天AMEYA360对尼得科科宝电子滑动型DIP开关各系列参数进行详细介绍,方便大家选择适合自己的型号。 系列一、滑动型DIP开关 CVS 针脚数:1, 2, 3, 4, 8 安装类型:表面贴装,通孔 可水洗:无 端子类型:PC引脚(只…...

一起学算法(滑动窗口篇)
前言: 对于滑动窗口,有长度固定的窗口,也有长度可变的窗口,一般是基于数组进行求解,对于一个数组中两个相邻的窗口,势必会有一大部分重叠,这部分重叠的内容是不需要重复计算的,所以我…...
HTML <q> 标签
实例 标记短的引用: <q>Here is a short quotation here is a short quotation</q>浏览器支持 元素ChromeIEFirefoxSafariOpera<q>YesYesYesYesYes所有浏览器都支持 <q> 标签。 定义和用法 <q> 标签定义短的引用。 浏览器经常在引用的内容…...

机器学习02-再识K邻近算法(自定义数据集训练及测试)
定义: 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。简单的说就是根据你的“邻居”来推断出你的类别。 用个成语就是物以类聚 思想: 如果一个样本在特征空间中的K个最…...
github使用笔记及git协作常用命令
1.Github有一个主库,每个人自己也有一个库,称为分支。 2.Github的协作流程:先从主库fork出自己的分支, 然后进行代码的修改等操作, 操作完之后从本地库上推到自己的服务器分支,然后 服务器分支Pull Request到 主库。 3.本地仓库由git维护的三棵“树"组成:第1个…...

iOS - Apple开发者账户添加新测试设备
获取UUID 首先将设备连接XCode,打开Window -> Devices and Simulators,通过下方位置查看 之后登录(苹果开发者网站)[https://developer.apple.com/account/] ,点击设备 点击加号添加新设备 填写信息之后点击Continue,并一路继续…...
vue 前端 邮箱、密码、手机号码等输入验证规则
最近在写前端表单验证的时候,发现一篇文章质量很好,所以写下这篇文章记录 原文章链接:vue 邮箱、密码、手机号码等输入验证规则 1.手机号 const checkPhone (rule, value, callback) > {const phoneReg /^1[34578]\d{9}$$/;if (!value…...

如何看待前端已死这个问题(大学生篇)
小编刚大学毕业,还记得是大三的时候选择的前端开发方向,那个时候行情其实并没有这么差,最近互联网上讨论这一个很火的话题,叫前端已死。那么我就说说我的看法吧,虽然可能比起行业的大佬会比较短浅,但我想就…...

揭开高级产品经理思维的秘密
我经常被问到产品经理如何晋升到更高级别。事实上,获得晋升往往是一场复杂的游戏。是的,你的技能和成就很重要,但其他因素也很重要,比如你的经理对人才培养的关心程度、你的同事有多优秀、任期有多长、公司的政治氛围如何等等。 所…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...