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

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 of num 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, and FnOnce. 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:

  1. 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.

  2. FnMut can mutate and also consume variables from the environment in which it is defined.

  3. 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代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

「JVM」性能调优工具

「JVM」性能调优工具 一、jcmd1、jcmd 能干嘛&#xff1f;2、与JVM相关的命令3、示例 二、jmap1、jmap有什么用&#xff1f;2、jmap的命令大全3、示例 三、jps1、jps有什么用&#xff1f;2、jps命令以及示例 四、jstat1、jstat有什么用&#xff1f;2、jstat命令以及示例 五、js…...

IDEA Debug小技巧 添加减少所查看变量、查看不同线程

问题 IDEA的Debug肯定都用过。它下面显示的变量&#xff0c;有什么门道&#xff1f;可以增加变量、查看线程吗&#xff1f; 答案是&#xff1a;可以。 演示代码 代码如下&#xff1a; package cn.itcast.attempt.threadAttempt.attempt2;public class Test {public static …...

基于SpringBoot+Vue的车辆充电桩管理系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…...

Bean的加载方式

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

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(13)-Fiddler请求和响应断点调试

1.简介 Fiddler有个强大的功能&#xff0c;可以修改发送到服务器的数据包&#xff0c;但是修改前需要拦截&#xff0c;即设置断点。设置断点后&#xff0c;开始拦截接下来所有网页&#xff0c;直到取消断点。这个功能可以在数据包发送之前&#xff0c;修改请求参数&#xff1b…...

Android 13(T) - Media框架(1)- 总览

从事Android Media开发工作三年有余&#xff0c;刚从萌新变成菜鸟&#xff0c;一路上跌跌撞撞学习&#xff0c;看了很多零零碎碎的知识&#xff0c;为了加深对Android Media框架的理解&#xff0c;决定在这里记录下学习过程中想到的一些问题以及一些思考&#xff0c;也希望对初…...

简述vue3(ts)+antdesignvue项目框架搭建基本步骤

目录 项目简介 概念 过程简述 基本步骤 1.创建新项目 2.安装Ant Design Vue 3.配置Ant Design Vue 4.创建页面和组件 5.使用组件 6.运行项目 项目简介 概念 Vue 3&#xff08;使用TypeScript&#xff09;和Ant Design Vue项目框架搭建是指在Vue 3框架下&#xff0c;…...

webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1

webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1 1.问题2. 解决办法&#xff1a; 1.问题 使用webpack打包是报错如下&#xff1a; webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c…...

GDAL OGR C++ API 学习之路 (5)OGRLayer篇 代码示例

GetStyleTable virtual OGRStyleTable *GetStyleTable () 返回图层样式表 返回: 指向不应由调用方修改或释放的样式表的指针 // 假设图层对象为 poLayer OGRStyleTable* poStyleTable poLayer->GetStyleTable(); if (poStyleTable ! nullptr) {// 处理样式表信息// ..…...

NIDEC COMPONENTS尼得科科宝滑动型DIP开关各系列介绍

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

一起学算法(滑动窗口篇)

前言&#xff1a; 对于滑动窗口&#xff0c;有长度固定的窗口&#xff0c;也有长度可变的窗口&#xff0c;一般是基于数组进行求解&#xff0c;对于一个数组中两个相邻的窗口&#xff0c;势必会有一大部分重叠&#xff0c;这部分重叠的内容是不需要重复计算的&#xff0c;所以我…...

HTML <q> 标签

实例 标记短的引用: <q>Here is a short quotation here is a short quotation</q>浏览器支持 元素ChromeIEFirefoxSafariOpera<q>YesYesYesYesYes所有浏览器都支持 <q> 标签。 定义和用法 <q> 标签定义短的引用。 浏览器经常在引用的内容…...

机器学习02-再识K邻近算法(自定义数据集训练及测试)

定义&#xff1a; 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别&#xff0c;则该样本也属于这个类别。简单的说就是根据你的“邻居”来推断出你的类别。 用个成语就是物以类聚 思想&#xff1a; 如果一个样本在特征空间中的K个最…...

github使用笔记及git协作常用命令

1.Github有一个主库,每个人自己也有一个库,称为分支。 2.Github的协作流程:先从主库fork出自己的分支, 然后进行代码的修改等操作, 操作完之后从本地库上推到自己的服务器分支,然后 服务器分支Pull Request到 主库。 3.本地仓库由git维护的三棵“树"组成:第1个…...

iOS - Apple开发者账户添加新测试设备

获取UUID 首先将设备连接XCode&#xff0c;打开Window -> Devices and Simulators&#xff0c;通过下方位置查看 之后登录(苹果开发者网站)[https://developer.apple.com/account/] &#xff0c;点击设备 点击加号添加新设备 填写信息之后点击Continue&#xff0c;并一路继续…...

vue 前端 邮箱、密码、手机号码等输入验证规则

最近在写前端表单验证的时候&#xff0c;发现一篇文章质量很好&#xff0c;所以写下这篇文章记录 原文章链接&#xff1a;vue 邮箱、密码、手机号码等输入验证规则 1.手机号 const checkPhone (rule, value, callback) > {const phoneReg /^1[34578]\d{9}$$/;if (!value…...

如何看待前端已死这个问题(大学生篇)

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

揭开高级产品经理思维的秘密

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

终极B站视频下载教程:3分钟学会免费下载4K高清内容

终极B站视频下载教程&#xff1a;3分钟学会免费下载4K高清内容 【免费下载链接】bilibili-downloader B站视频下载&#xff0c;支持下载大会员清晰度4K&#xff0c;持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 你是否经常在B站看到精…...

技术人做知识付费,月入5万的底层逻辑拆解

一、认知破局&#xff1a;从“技术执行者”到“知识提供者”对于软件测试从业者而言&#xff0c;在知识付费领域实现月入5万&#xff0c;首先要完成的是认知层面的重塑。长期以来&#xff0c;测试人员被定位为“技术执行者”&#xff0c;核心工作围绕着编写测试用例、执行测试脚…...

如何快速为OpenWrt路由器安装Turbo ACC网络加速:终极性能优化指南

如何快速为OpenWrt路由器安装Turbo ACC网络加速&#xff1a;终极性能优化指南 【免费下载链接】turboacc 一个适用于官方openwrt(22.03/23.05/24.10) firewall4的turboacc 项目地址: https://gitcode.com/gh_mirrors/tu/turboacc 还在为路由器卡顿、网络延迟而烦恼吗&am…...

翻转电饼铛生产厂家:高性价比背后的运营策略深度解析

翻转电饼铛生产厂家&#xff1a;高性价比背后的运营策略深度解析“高性价比不是低价竞争&#xff0c;而是让设备价值与企业需求精准匹配”——这是优质翻转电饼铛生产厂家的核心运营逻辑。很多食品企业在选购翻转电饼铛时&#xff0c;既担心高价设备增加成本&#xff0c;又怕低…...

AppleRa1n终极指南:三步解锁iPhone激活锁,让你的旧设备重获新生

AppleRa1n终极指南&#xff1a;三步解锁iPhone激活锁&#xff0c;让你的旧设备重获新生 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 还在为忘记Apple ID密码而烦恼吗&#xff1f;或者刚买的二手iPh…...

Asp.net Mvc教学: LINQ相关的几大分类的使用率-由Deepseek产生

基于当前&#xff08;2026年&#xff09;.NET开发生态的实际情况&#xff0c;这五大方法的使用率呈现出非常明显的两极分化趋势。 简单直接地回答&#xff1a;使用率高的只有两个&#xff0c;其他三个使用率极低&#xff0c;属于特定场景工具。 以下是具体的排名与解析&#xf…...

手把手带你用C语言模拟RISC-V的`li`指令扩展过程(附完整代码)

手把手带你用C语言模拟RISC-V的li指令扩展过程&#xff08;附完整代码&#xff09; 在计算机体系结构的学习中&#xff0c;理解指令集的工作原理是掌握底层编程的关键。RISC-V作为一种开源指令集架构&#xff0c;近年来在学术界和工业界都获得了广泛关注。本文将带领读者通过C语…...

Jetson Nano到手后别急着烧系统,先做好这5步准备(含SD卡选购与电源避坑)

Jetson Nano开箱必做的5项硬件准备&#xff1a;从SD卡到电源的完整避坑指南 当你第一次拿到Jetson Nano开发板时&#xff0c;那种迫不及待想立刻通电体验的冲动完全可以理解。但作为一个经历过多次"翻车"的老玩家&#xff0c;我必须提醒你&#xff1a;直接烧录系统很…...

ETS2LA:欧洲卡车模拟2自动驾驶插件的完整指南

ETS2LA&#xff1a;欧洲卡车模拟2自动驾驶插件的完整指南 【免费下载链接】Euro-Truck-Simulator-2-Lane-Assist Plugin based interface program for ETS2/ATS. 项目地址: https://gitcode.com/gh_mirrors/eur/Euro-Truck-Simulator-2-Lane-Assist 你是否曾经在长途运输…...

告别CNN!用PyG Temporal和GC-LSTM搞定动态社交网络的好友推荐(附完整代码)

动态社交网络好友推荐的工程实践&#xff1a;基于GC-LSTM与PyG Temporal的完整解决方案 社交网络的动态特性为传统推荐系统带来了巨大挑战。当用户关系每分每秒都在变化时&#xff0c;静态的协同过滤或内容推荐方法往往显得力不从心。本文将分享如何利用PyG Temporal库和GC-LST…...