坏蛋Dan
知乎@坏蛋Dan
发布时间:2024.1.4

前言

昨天我们学了闭包

坏蛋Dan:rust基础学习--day29

今天我们往下学Iterator


Iterator

迭代器相信大家之前有接触过。

rust中,迭代器是lazy的,也就是惰性的。在你把这个迭代器消耗(consume)完之前,它是不会做任何影响的。

比如:

调用集合类型都有的iter方法创建一个迭代器。这个是完全没有影响的。

然后我们来用个for遍历他

这个时候,每当超过当前item作用域之后这个iterator就会被消耗一层,然后再进入下一层item

iterator traitnext方法

所有的迭代器都实现了标准库里一个叫Iteratortrait。 大概张这个样子,由于截图太长了,没法放进来

这里有一个我们并不认识的语法type Item,实际上是后面会学到的associate type也就是关联类型。

它要求我们在impl这个Iterator的时候也需要定义一个自己的Item类型。它会被用在next这个方法中,以Some(Item)的方式返回。

另外Iterator 这个trait只需要我们在实现的时候把next这个方法实现即可。 这个next的方法会在每一次迭代的时候返回一个Some(Item),然后在迭代结束的时候返回None

我们可以直接对迭代器的实例使用next这个方法,比如

需要注意的一点是迭代器得是mut的。

iter这个method返回的是不可变的借用,如果想要获得所有权,可以调用into_iter,会返回不可变的所有权,如果想要可变的可以调用into_mut


会消耗(consume)迭代器的method

Iterator有一堆api是用来消耗迭代器的,其中最经典的自然就是next这个method

rust团队管这种method叫做*consuming adaptors,*也就是消耗适配器。

每次调用都会消耗一个迭代器。

另外还有一个是sum,它会获得迭代器的所有权(记住这一点),然后迭代这个迭代器里所有的项通过重复的调用next方法,把每个项加起来最后返回。

我们来看个例子


会产生(produce)其它迭代器的method

Iterator adaptors 也就是迭代器适配器,它们不会消耗迭代器。

相反,它们会返回一个其它的迭代器通过某些方面改动原来的迭代器。

比如map方法,它相信大家应该不陌生,ES6+中提供的高级函数(指接收一个function作为参数)。

rust中的map是迭代器的method,它是一个迭代器适配器,也就是说不会消耗迭代器并且最终会返回一个新的迭代器。

来看下例子

它接受一个闭包作为参数,并且迭代器的项会作为参数传入闭包中。

看了源码应该可以知道并不会立即执行闭包,而是得等新的迭代器被使用的时候才会执行。

也就是前面说的:lazy,只有在调用消耗适配器的时候才会执行。

我们可以直接调用collect方法把这个迭代器转换为一个集合,这也是一种consume

然后我们还可以链式调用,比如map(xxx).filter(....).collect,因为迭代器适配器最终都是返回一个迭代器,所以不用担心链会断掉。 最后再用消耗适配器来消耗掉迭代器即可。


总结

迭代器还是比较简单的,不过大多数时候迭代器是和闭包一起使用的,我们这里涉及不多. 不过前路漫漫,早晚遇到.

参考

  1. ^rust-iterator https://doc.rust-lang.org/book/ch13-02-iterators.html#processing-a-series-of-items-with-iterators
  2. ^rust-iterator-trait-and-next-method https://doc.rust-lang.org/book/ch13-02-iterators.html#the-iterator-trait-and-the-next-method
  3. ^rust-13.2-method-that-consume-iterator https://doc.rust-lang.org/book/ch13-02-iterators.html#methods-that-consume-the-iterator

发布于 2022-12-28 11:58・IP 属地广东