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

【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来迭代项目,从而消耗迭代器。在迭代时,它将每个项目添加到运行总和中,并在迭代完成时返回总和。

#[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方法为例,它接收一个闭包,闭包作用于迭代器的每个元素。它把当前迭代器的每个元素给转换为另外一个元素,然后这些另外的元素就组成了一个新的迭代器。

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的操作,除非调用一些消耗性的方法:

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

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


http://www.kler.cn/a/511250.html

相关文章:

  • 架构思考与实践:从通用到场景的转变
  • 力扣hot100之螺旋矩阵
  • 大数据时代的璀璨明珠:机器学习引领的智能应用革新与深度融合探索
  • 正态分布检验(JB检验和威尔克检验)和斯皮尔曼相关系数(继上回)
  • 深入理解 SQL 中的 DATEDIFF 函数
  • 西门子【Library of Basic Controls (LBC)基本控制库”(LBC) 提供基本控制功能】
  • React实现拖拽特效
  • QT入门的一些吐槽
  • 二叉树02(数据结构初阶)
  • Go语言的文件操作
  • 【K8S系列】K8s 领域深度剖析:年度技术、工具与实战总结
  • 十一、apply家族(4)
  • 【QT用户登录与界面跳转】
  • Spring Boot 项目启动报错 “找不到或无法加载主类” 解决笔记
  • “UniApp的音频播放——点击视频进入空白+解决视频播放器切换视频时一直加载的问题”——video.js、video-js.css
  • 短链接功能实现
  • 通过ShiftMediaProject生成ffmpeg的DLL和Lib的简要说明
  • 几何数据结构之四叉树与八叉树
  • IDEA运行测试函数@Test注解旁边没有运行按钮
  • Python脚本搬运当前文件夹及其子文件夹中所有的.c格式的文件到当前新建的文件夹中
  • 什么是软件架构
  • Ansible自动化运维:基础与实践
  • js经典例题之var a = b = c = 9;
  • 解决后端接口返回Long类型参数导致的精度丢失问题
  • react使用react-redux状态管理
  • 【cursor重构谷粒商城】03——谷粒商城技术架构选型存在哪些不足?