Rust语言入门教程(十四) - 闭包Closure

2023-11-30 10:20

本文主要是介绍Rust语言入门教程(十四) - 闭包Closure,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是闭包

闭包在 Rust 中是非常强大的功能,允许你编写更灵活和表达性的代码。闭包的语法和功能在某些方面类似于其他语言(如 JavaScript 或 Python)中的匿名函数或 lambda 表达式。

在Rust中,当我们想要生成一个新的线程,或者是想在迭代中进行一些函数式编程对迭代变量进行处理时,通常就会用到闭包, 当然,在标准库中一些其他的常见的地方,也会涉及到闭包的使用。

闭包本质上是一个匿名函数,它可以从其所在的作用域中借用或捕获到一些变量或数据。

语法规范

|x, y| { x+y }

上面的代码展示了一个闭包的基本语法格式:

  • 在两个|之间是闭包的参数列表,参数之间用,分隔;
  • 参数不需要标注数据类型;
  • 竖线后面是一个匿名函数的代码块,可以用于代码调用;

其中,参数的类型和和匿名函数的返回值都是由编译器通过代码的上下文自动推断得出。让我们来看一个实际的例子:

let add = |x, y| { x + y };
add(1, 2); // return 3

上面的代码中,我们将闭包分配给了一个变量add, 然后通过传入参数1, 2调用这个闭包,这两个变量将被传入匿名函数执行,并返回3

捕获变量

闭包的参数列表可以为空,因此上面的例子可以是这样:

|| { x + y }

当然,匿名函数也可以为空,比如这样:

|| {}

但是显然这样做没什么意义,也没人会干这么无聊的事情。那么为什么参数列表可以为空呢,那匿名函数中的变量从何而来呢? 这就到了有意思的地方了, 闭包可以借用它被定义的作用域中的值的引用。

let s = "abc".to_string();
let f = || {println!("{}", s);
};f() // 输出 “abc”

在上面的代码中,我们创建了一个字符串变量s, 然后创建了一个闭包并分配给变量f, 其中的匿名函数借用了该作用域中变量s的引用(因为println!是使用的参数的引用), 从而匿名函数本身不需要参数列表。这样一来,我们每次通过变量f调用这个匿名函数时,都可以打印出abc

所有权移动 - move

但是这存在一个问题,匿名函数中只是借用了变量s的引用,如果变量s一旦超出作用域而被销毁, f中的引用就成为了一个悬空指针,这是Rust编译器所不允许的。

为了解决这个问题, 闭包也支持使用move关键字,来强制的将闭包中使用的任何变量移动到自身的作用域中并获取他们的所有权,而不再只是借用。

let s = "abc".to_string();
let f = move || {println!("{}", s);
};f();

这样一来s的所有权便被闭包拥有,它将一直存在,直至闭包本身超出作用域被销毁为止。我们可以把这个闭包传递给另一个线程,或者作为函数的返回值返回,等等。

在迭代器中使用闭包

如果想在迭代器中进行一些函数式的编程,对迭代变量进行处理,闭包也是真香。

let mut v = vec![2, 4, 6];
v.iter().map(|x| x * 3).filter(|x| *x > 10).fold(0, |acc, x| acc + x)

上面的代码中,对一个向量调用iter()函数,获得了一个迭代器,将对这个向量中的每个值进行迭代。然后就可以多种多样的使用到闭包的方法了。

  • map(): 对向量中每个项都乘以3;
  • filter(): 丢弃向量中不大于10的项;
  • fold(): 将筛选后的向量中的所有的值相加求和;

小结

本章介绍了Rust中闭包的概念和使用场景,已经如何将变量的所有权转移到闭包中。下一章我们将讨论Rust的多线程。

这篇关于Rust语言入门教程(十四) - 闭包Closure的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/436658

相关文章

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、

Rust中的注释使用解读

《Rust中的注释使用解读》本文介绍了Rust中的行注释、块注释和文档注释的使用方法,通过示例展示了如何在实际代码中应用这些注释,以提高代码的可读性和可维护性... 目录Rust 中的注释使用指南1. 行注释示例:行注释2. 块注释示例:块注释3. 文档注释示例:文档注释4. 综合示例总结Rust 中的注释

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

使用Go语言开发一个命令行文件管理工具

《使用Go语言开发一个命令行文件管理工具》这篇文章主要为大家详细介绍了如何使用Go语言开发一款命令行文件管理工具,支持批量重命名,删除,创建,移动文件,需要的小伙伴可以了解下... 目录一、工具功能一览二、核心代码解析1. 主程序结构2. 批量重命名3. 批量删除4. 创建文件/目录5. 批量移动三、如何安

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑