【Rust自学】13.6. 迭代器 Pt.2:消耗和产生迭代器的方法

13.6.0. 写在正文之前

Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。

在本章中,我们会讨论 Rust 的一些特性,这些特性与许多语言中通常称为函数式的特性相似:

  • 闭包
  • 迭代器(本文)
  • 使用闭包和迭代器改进I/O项目
  • 闭包和迭代器的性能

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

13.6.1. 消耗迭代器的方法

在标准库中,Iterator trait有一些带默认实现的方法。其中有一些会调用next方法,所以说想实现Iterator trait就必须实现next方法。

调用next方法的方法叫做"消耗性适配器 ",因为next方法会把迭代器内的元素一个一个消耗掉,最终会把迭代器耗尽。

举个例子,sum方法会获取迭代器的所有权,并通过重复调用next来迭代项目,从而消耗迭代器。在迭代时,它将每个项目添加到运行总和中,并在迭代完成时返回总和。

rust 复制代码
#[cfg(test)]
mod tests {
    #[test]
    fn iterator_sum() {
        let v1 = vec![1, 2, 3];
        let v1_iter = v1.iter();
        let total: i32 = v1_iter.sum();
        assert_eq!(total, 6);
    }
}

13.6.2. 产生其它迭代器的方法

Iterator trait上还定义了其它方法,叫做"迭代器适配器"。它们会把当前的迭代器转换为不同种类的迭代器。而且你可以通过链式调用多个迭代器适配器来执行复杂的操作,这种调用可读性较高。

map方法为例,它接收一个闭包,闭包作用于迭代器的每个元素。它把当前迭代器的每个元素给转换为另外一个元素,然后这些另外的元素就组成了一个新的迭代器。

rust 复制代码
let v1: Vec<i32> = vec![1, 2, 3];
v1.iter().map(|x| x + 1);

这段代码会对Vector内的每个元素执行加1的操作。

这么写本身没有问题,但是编译器会产生警告:

复制代码
$ cargo run
   Compiling iterators v0.1.0 (file:///projects/iterators)
warning: unused `Map` that must be used
 --> src/main.rs:4:5
  |
4 |     v1.iter().map(|x| x + 1);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: iterators are lazy and do nothing unless consumed
  = note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
  |
4 |     let _ = v1.iter().map(|x| x + 1);
  |     +++++++

warning: `iterators` (bin "iterators") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.47s
     Running `target/debug/iterators`

由于Rust的迭代器是惰性的,如果你没有消耗它们(指你不调用那些消耗性适配器方法 ),那么它们就什么都不会做。也就是说现在这个状态它并不会对Vector里的三个元素进行加1的操作,除非调用一些消耗性的方法:

rust 复制代码
let v1: Vec<i32> = vec![1, 2, 3];
let v2:Vec<_> = v1.iter().map(|x| x + 1).collect();

这里使用了collect这个消耗性的适配器方法,把结果收集到某个类型的集合里。由于可以collect可以转很多集合类型,所以这里得显式声明v2的类型是Vector,也就是写Vec<_>Vec<_>_代表让编译器自行推断元素的类型。

相关推荐
夕颜1112 分钟前
记录一下关于 Cursor 设置的问题
后端
凉白开3383 分钟前
Scala基础知识
开发语言·后端·scala
不要不开心了4 分钟前
Scala内容
开发语言·pytorch·flask·scala·dash
2401_824256865 分钟前
Scala的函数式编程
开发语言·后端·scala
幻想趾于现实23 分钟前
C# Winform 入门(2)之发送邮件
开发语言·c#
SoFlu软件机器人27 分钟前
Go/Rust 疯狂蚕食 Java 市场?老牌语言的 AI 化自救之路
java·golang·rust
半盏茶香29 分钟前
启幕数据结构算法雅航新章,穿梭C++梦幻领域的探索之旅——堆的应用之堆排、Top-K问题
java·开发语言·数据结构·c++·python·算法·链表
小吴先生6661 小时前
Groovy 规则执行器,加载到缓存
java·开发语言·缓存·groovy
小杨4041 小时前
springboot框架项目实践应用十四(扩展sentinel错误提示)
spring boot·后端·spring cloud
陈大爷(有低保)1 小时前
Spring中都用到了哪些设计模式
java·后端·spring