rust 闭包函数

函数有自己的类型,可以像使用基础类型一样使用函数,包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数,也有自己的类型定义。不过,函数实际上是指针类型,在 rust 所有权中属于借用的关系。

我们声明一个 Vec 对象集,并使用闭包函数做排序。接下来我们自定义一个 City 结构体类型,Vec 中的每个元素都是 City 类型,后面会根据结构体中的 population 属性做排序。

#[derive(Debug)]
struct City {
    name: String,
    population: i64,
    country: String,
}

我们初始化 cities 变量,并向其中依次追加 3 个元素。vec 追加元素使用 push 函数,push 过程也会触发底层数组的扩容。rust 也提供了初始化指定 vec 容量的函数 with_capacity。

fn main() {
    let mut cities: Vec<City> = vec![];
    cities.push(City {
        name: ("上海".to_string()),
        population: (123i64),
        country: ("China".to_string()),
    });
    cities.push(City {
        name: ("北京".to_string()),
        population: (12i64),
        country: ("China".to_string()),
    });
    cities.push(City {
        name: ("广州".to_string()),
        population: (124i64),
        country: ("China".to_string()),
    });
    sort_cities(&mut cities);
    println!("{:?}", cities)
}

sort_cities 算是这篇文章的关键函数了,函数内部使用到了闭包。想要彻底明白下面的逻辑,首先要了解 sort_by_key 函数,这个函数的入参是一个闭包函数。

fn sort_cities(cities: &mut Vec<City>) {
    cities.sort_by_key(|city| -city.population);
}

声明中的 &mut self 表示方法能够可变地借用 self 实例,支持对它进行修改。闭包函数的类型是 FnMut(&T),返回的类型需要满足 Ord 约束。从声明中可以看出,闭包函数是有类型的,同时,返回的类型必须是可排序的。

在这里插入图片描述

代码部分,闭包函数的写法特别简单,两个竖线是闭包函数识别的标志。尽管闭包函数要求有返回值,但代码中并没有体现,都是 rust 自己默认推断实现的。

我们尝试对代码部分的闭包声明做写法上的调整,下面的闭包声明都是相同的。

// 加了代码块
fn sort_cities(cities: &mut Vec<City>) {
    cities.sort_by_key(|city| {-city.population});
}
// 加了入参声明
fn sort_cities(cities: &mut Vec<City>) {
    cities.sort_by_key(|city: &City| -city.population);
}
// 加了返回值声明
fn sort_cities(cities: &mut Vec<City>) {
    cities.sort_by_key(|city| -> i64 { -city.population });
}

闭包引用对象的所有权

在闭包函数体中使用外部的变量,会导致外部变量的所有权发生变更吗?如果是 go 语言,外部变量在闭包中是通过引用来访问的。具体到 rust 语言上,我们可以通过自定义闭包函数验证一番。

我们在原代码基础上做了简化,is_long_name 函数体中直接访问外部变量 sh,并将 sh 的名字重新赋值一个新的变量 name。编译器检测到 sh.name 发生了所有权转移,编译失败。

fn main() {
    let sh = City {
        name: ("上海".to_string()),
        population: (123i64),
        country: ("China".to_string()),
    };

    let is_long_name = || -> bool {
        let name = sh.name;
        if name.len() > 2 {
            true
        } else {
            false
        }
    };

    is_long_name();
    println!("{:?}", sh);
}

在这里插入图片描述

在闭包声明的开头,大家也看到过 move 关键字。那么,这个 move 是用来解决什么问题的呢?

针对这个例子,我们专门在闭包内对 sh.name 重新做了赋值运算,变量所有权发生转移也符合认知。那么,我们现在直接使用 sh.name 进行长度判断,对应截图中的第 13 行代码。左右差异点只有:右边的闭包声明中追加生 move 关键字。

在这里插入图片描述

在这里插入图片描述

rust 中闭包取得数据有两种方式:转移和借用。move 会导致使用到的外部变量发生所有权转移。右边的例子中,闭包中的变量 sh.name 的所有权就发生了转移,导致编译失败。

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

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

相关文章

小白带你学习linux的mysql服务(主从mysql服务和读写分离三十一)

目录 二、MySQL Replication优点&#xff1a; 三、MySQL复制类型 1、异步复制&#xff08;Asynchronous repication&#xff09; 2、全同步复制&#xff08;Fully synchronous replication&#xff09; 3、半同步复制&#xff08;Semisynchronous replication&#xff09;…

设计模式-中介者模式在Java中使用示例-客户信息管理

场景 欲开发客户信息管理窗口界面&#xff0c;界面组件之间存在较为复杂的交互关系&#xff1a;如果删除一个客户&#xff0c; 要在客户列表(List)中删掉对应的项&#xff0c;客户选择组合框(ComboBox)中客户名称也将减少一个&#xff1b; 如果增加一个客户信息&#xff0c;…

网络安全行业相关证书

一&#xff1a;前言 对于考证这个话题&#xff0c;笔者的意见是&#xff1a;“有比没有好&#xff0c;有一定更好&#xff0c;但不一定必须&#xff1b;纸上证明终觉浅&#xff0c;安全还得实力行”。很多人对于各种机构的考证宣传搞得是云里雾里&#xff0c;不知道网络安全行业…

fastadmin采坑之固定表格某一列

// 初始化表格table.bootstrapTable({url: $.fn.bootstrapTable.defaults.extend.index_url,pk: id,sortName: id,fixedColumns: true,fixedRightNumber: 1,columns: [[{checkbox: true},{field: id, title: __(Id)},{field: proposal_title, title: __(Proposal_title), opera…

动脑学院Jetpack Compose学习笔记

最近b站学习了一下Compose相关内容&#xff0c;整理了相关笔记&#xff0c;仅供大家参考。 资源链接如下&#xff0c;象征性收取1个积分 https://download.csdn.net/download/juliantem/88125198

【图论】树上差分(边差分)

一.简介 其实点差分和边差分区别不大。 点差分中&#xff0c;d数组存储的是树上的节点 边差分中&#xff0c;d数组存储的是当前节点到父节点的那条边的差分值。 指定注意的是&#xff1a;边差分中因为根连的父节点是虚点&#xff0c;所以遍历结果时应当忽略&#xff01; 二…

腾讯云—自动挂载云盘

腾讯云&#xff0c;稍微麻烦了点。 腾讯云服务器&#xff0c;镜像为opencloudos 8。 ### 1、挂载云盘bash #首先通过以下命令&#xff0c;能够看到新的数据盘&#xff0c;如果不能需要通过腾讯云控制台卸载后&#xff0c;重新挂载&#xff0c;并重启服务器。 fdisk -l#为 /dev…

Houdini查看参数能用的内置变量($符号开头的变量)

在某个参数上&#xff0c;右键&#xff0c;reference, local variable就能看到

Postman如何导出接口的几种方法

本文主要介绍了Postman如何导出接口的几种方法&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 前言&#xff1a; 我的文章还是一贯的作风&#xff0c;简确用风格&#xff08;简单确实有用&#xff09;&am…

金三银四好像消失了,IT行业何时复苏!

疫情时候不敢离职&#xff0c;以为熬过来疫情了&#xff0c;行情会好一些&#xff0c;可是疫情结束了&#xff0c;反而行情更差了&#xff0c; 这是要哪样 我心中不由一万个 草泥&#x1f434; 路过 我心中不惊有了很多疑惑和感叹&#xff01; 自我10连问 我的心情 自去年下…

HCIA实验二

实验要求&#xff1a; 1.R2为ISP&#xff0c;只能配置IP 2.R1-R2之间为HDLC封装 3.R2-R3之间为PPP封装&#xff0c;pap认证&#xff0c;R2为主认证方 4.R2-R4之间为PPP封装&#xff0c;chap认证&#xff0c;R2为主认证方 5.R1、R2、R3构建MGRE&#xff0c;仅R1的IP地址固定…

vmware的window中安装GNS3

1.向vmware中的windows虚拟机传送文件 点击虚拟机-安装VMwaretools 安装在虚拟机上面 此图标代表已经成功&#xff0c;将文件复制到虚拟机上里面 2.安装 安装gns3&#xff0c;需要先安装winpcap&#xff08;检查网卡&#xff09;和wireshark&#xff08;对winpcap上数据进行抓…

excel绘制折线图或者散点图

一、背景 假如现在通过代码处理了一批数据&#xff0c;想看数据的波动情况&#xff0c;是不是还需要写个pyhon代码&#xff0c;读取文件&#xff0c;绘制曲线&#xff0c;看起来也简单&#xff0c;但是还有更简单的方法&#xff0c;就是直接生成csv文件&#xff0c;csv文件就是…

本地非文字资源无法加载

目录 方法A.静态/动态绑定路径 方法B.require导入&#xff08;运行时加载&#xff09; 方法C.import导入&#xff08;x&#xff09;&#xff08;编译时加载&#xff09; 方法D.ref直接操作元素赋值&#xff08;x&#xff09; 相关知识 import和requir区别 模板路径&#…

华为华三思科 交换机基础配置一览

console密码修改 华为 user-interface console 0 authentication-mode password set authentication password cipher XXXXXXXXX华三 line aux 0 authentication-mode password set auth pass simple XXX思科 en configure terminal line console 0 password 123 login忘记…

❤️创意网页:打造炫酷网页 - 旋转彩虹背景中的星星动画

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

【C++ 进阶】学习导论:C/C++ 进阶学习路线、大纲与目标

目录 一、C 学习路线 二、C 课程大纲与学习目标 &#xff08;1&#xff09;第一阶段&#xff1a;C 语言基础 &#xff08;2&#xff09;第二阶段&#xff1a;C 高级编程 &#xff08;3&#xff09;第三阶段&#xff1a;C 核心编程与桌面应用开发 &#xff08;4&#xf…

OAuth机制_web站点接入微软azure账号进行三方登录

文章目录 ⭐前言⭐微软三方登录流程&#x1f496; web站点获取微软账号流程&#x1f496; node封装微软登录接口&#x1f496; webapp 自定义code换token&#x1f496; 调用 Microsoft Graph API&#x1f496; 前端唤醒authlink进行登录回调逻辑 ⭐结束 ⭐前言 大家好&#xf…

深度学习论文: Q-YOLO: Efficient Inference for Real-time Object Detection及其PyTorch实现

深度学习论文: Q-YOLO: Efficient Inference for Real-time Object Detection及其PyTorch实现 Q-YOLO: Efficient Inference for Real-time Object Detection PDF: https://arxiv.org/pdf/2307.04816.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代…

【论文笔记】神经网络压缩调研

神经网络压缩调研 背景现有的深度模型压缩方法NetWork Prunning 网络剪枝设计结构化矩阵知识蒸馏权值共享Parameter Quantization&#xff08;参数量化&#xff09;量化和二进制化伪量化Architecture Design&#xff08;Depth Separable Convolution&#xff09;分解卷积 背景 …