【RUST学习日记】第20课 闭包

简介: 【RUST学习日记】第20课 闭包

0x00 回顾与开篇


我们已经通过两节课介绍了Rust的函数使用方法,尤其是要学会使用Rust的高阶函数,它在后续的项目编写中会变得很常用。这节课学习函数的另一种表现形式——闭包(Closure),有些人也被称其为匿名函数,但不准确。


0x01 闭包的定义


闭包(Closure)通常是指词法闭包,是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量,在函数式编程范式中也被称为自由变量,是指并不是在闭包内定义的变量。将自由变量和自身绑定的函数就是闭包。闭包通常有参数列表(由两条竖线包裹)和表达式组成,语法形式如下。

| parameters | expression

示例代码如下:

let add = |a, b| a + b;
    // let add: fn(i32, i32) -> i32 = |a, b| a + b;
    let result = add(1, 2);
    // let result = add(1.2, 3.4);
    dbg!(result);

代码运行结果:

result = 3

解释下上面的代码,第一行代码声明了一个函数类型,其使用闭包语法创建的。我们没有为其指定类型,它会根据上下文推断为fn(i32, i32) -> i32类型,相当于第二行注释。再看第4行注释的代码,如果将它打开则会报错,因为前面已经将其推断为fn(i32, i32) -> i32类型,不再接收其它类型。从上面的代码来看,又感觉闭包是简化版的函数。


0x02 从函数到闭包


下面用一个例子来看下从函数到闭包经过了哪些变化。

首先我们先定义一个函数

fn add(a:i32, b:i32) -> i32 {a + b}

转成闭包,使用let关键字声明,括号变成管道符号。最后添加分号结束。

let add = |a:i32, b:i32|->i32 {a + b};

简化,去除参数类型的声明。闭包并不像函数那样严格要求注明函数类型和返回值类型,去除括号。

let add = |a, b| {a + b};

继续简化,

let add = |a, b| a + b;


0x03 捕获变量


在闭包中还存在一个特点,它可以捕获和使用其被定义时所在的作用域中的变量。

示例代码如下:

let k = 8;
    let add_var = |a| a + k;
    let result = add_var(10);
    dbg!(result);

代码运行结果:

result = 18


0x04 小结


本节介绍了Rust的闭包。总结下闭包的特点吧。

  • 闭包不严格要求注明参数和返回值类型
  • 不注明类型的闭包,若多次调用但传递不同类型,则会发生错误
  • 闭包可以捕获和使用其所在作用域中的变量
  • 闭包通常适用于相对较小的场景上下文
  • 闭包性能要快于函数指针(后续章节会详细介绍)

本节课仅仅是简单介绍了闭包的使用,关于闭包其实还有更多的知识点。在后续的Rust进阶课程中我会再次讲解闭包。

相关文章
|
9天前
|
存储 Rust 网络协议
【Rust学习】10_定义枚举
在这一章我们学习 枚举(enumerations),也被称作 enums。枚举允许你通过列举可能的 成员(variants) 来定义一个类型。首先,我们会定义并使用一个枚举来展示它是如何连同数据一起编码信息的。接下来,我们会探索一个特别有用的枚举,叫做 Option,它代表一个值要么是某个值要么什么都不是。然后会讲到在 match 表达式中用模式匹配,针对不同的枚举值编写相应要执行的代码。最后,我们将学习 if let 结构,另一个简洁方便处理代码中枚举的结构。
25 7
|
30天前
|
Rust 算法 安全
学习Rust
【10月更文挑战第13天】学习Rust
52 8
|
1月前
|
Rust 安全 算法
Rust的学习
【10月更文挑战第12天】Rust的学习
27 2
|
1月前
|
Rust 算法 安全
如何学习Rust编程?
【10月更文挑战第12天】如何学习Rust编程?
41 1
|
1月前
|
Rust API
【Rust学习】09_方法语法
结构体让你可以创建出在你的领域中有意义的自定义类型。通过结构体,我们可以将相关联的数据片段联系起来并命名它们,这样可以使得代码更加清晰。在 impl 块中,你可以定义与你的类型相关联的函数,而方法是一种相关联的函数,允许您指定结构体的实例具有的行为。 但是结构体并不是创建自定义类型的唯一方式:让我们转向 Rust 的 enum 功能,将另一个工具添加到你的工具箱中。
14 0
|
2月前
|
Rust 索引
【Rust学习】08_使用结构体代码示例
为了了解我们何时可能想要使用结构体,让我们编写一个计算长方形面积的程序。我们将从使用单个变量开始,然后重构程序,直到我们改用结构体。
92 2
|
2月前
|
存储 Rust 编译器
【Rust学习】07_结构体说明
**struct**或 ***structure***是一种自定义数据类型,允许您命名和包装多个相关的值,从而形成一个有意义的组合。如果您熟悉面向对象的语言,那么**struct**就像对象中的数据属性。在本章中,我们将比较和对比元组与结构体,在您已经知道的基础上,来演示结构体是对数据进行分组的更好方法。
24 1
|
3月前
|
存储 Rust 安全
【Rust学习】06_切片
所有权、借用和切片的概念确保了 Rust 程序在编译时的内存安全。Rust 语言提供了跟其他系统编程语言相同的方式来控制你使用的内存,但拥有数据所有者在离开作用域后自动清除其数据的功能意味着你无须额外编写和调试相关的控制代码。
25 1
|
2月前
|
Rust Linux Go
Rust/Go语言学习
Rust/Go语言学习
|
4月前
|
存储 Rust 安全
【Rust学习】04_所有权
所有权是 Rust 最独特的特性,对语言的其余部分有着深远的影响。它使 Rust 能够在不需要垃圾收集器的情况下保证内存安全,因此了解所有权的运作方式非常重要。在本章中,我们将讨论所有权以及几个相关功能:借用、切片以及 Rust 如何在内存中布局数据。
26 1