bigywater.tech
Rust · 52

Iterator Trait

Iterator 是 Rust 里使用最频繁的 trait,整个 for 循环与几十个适配器都建立在它的 next() 上。这篇从最底层验证它的约定:next 与 None、状态与 mut、size_hint 的上下界、双端与部分消耗,以及不写 struct 就能造迭代器的几个函数。

next()
Iterator 唯一必须实现的方法
(0, Some(5))
filter 之后 size_hint:下界为 0
E0596
迭代器变量没写 mut 就调用 next

next 与 for

实测 · 本机执行输出
  源码:
      1 | fn main() {
      2 |     let v = vec![10, 20, 30];
      3 |     let mut it = v.iter();
      4 |     println!("{:?} {:?} {:?} {:?} {:?}", it.next(), it.next(), it.next(), it.next(), it.next());
      5 |     println!("手写的 for 展开:");
      6 |     let mut it = v.iter();
      7 |     while let Some(x) = it.next() { println!("  元素 {x}"); }
      8 |     let mut it = v.into_iter().map(|x| x + 1);
      9 |     println!("map 适配器也是迭代器:{:?} {:?}", it.next(), it.next());
     10 |     println!("迭代器本身需要 mut:不写 mut 会报错(见下)");
     11 | }
  编译:成功
  运行(退出码 0):
    Some(10) Some(20) Some(30) None None
    手写的 for 展开:
      元素 10
      元素 20
      元素 30
    map 适配器也是迭代器:Some(11) Some(21)
    迭代器本身需要 mut:不写 mut 会报错(见下)
  编译:失败
    error[E0596]: cannot borrow `it` as mutable, as it is not declared as mutable
     --> <实验目录>/src/u52b.rs:1:49
      |
    1 | fn main() { let v = vec![1]; let it = v.iter(); it.next(); }
      |                                                 ^^ cannot borrow as mutable
      |
    help: consider changing this to be mutable
      |
    1 | fn main() { let v = vec![1]; let mut it = v.iter(); it.next(); }
      |                                  +++
    
    error: aborting due to 1 previous error
    
    For more information about this error, try `rustc --explain E0596`.

for 循环的展开见for 循环如何转换成 Iterator;适配器的惰性见Iterator 的惰性执行。

size_hint 与 ExactSizeIterator

实测 · 本机执行输出
  源码:
      1 | fn main() {
      2 |     let v = vec![1, 2, 3, 4, 5];
      3 |     println!("v.iter()                 size_hint = {:?}", v.iter().size_hint());
      4 |     println!("v.iter().map(..)         size_hint = {:?}", v.iter().map(|x| x * 2).size_hint());
      5 |     println!("v.iter().filter(..)      size_hint = {:?}(过滤后数量未知,下界为 0)", v.iter().filter(|x| **x > 2).size_hint());
      6 |     println!("v.iter().chain(v.iter()) size_hint = {:?}", v.iter().chain(v.iter()).size_hint());
      7 |     println!("v.iter().take(2)         size_hint = {:?}", v.iter().take(2).size_hint());
      8 |     println!("(0..).take(3)            size_hint = {:?}", (0..).take(3).size_hint());
      9 |     println!("(0..)                    size_hint = {:?}(无穷)", (0..).size_hint());
     10 |     println!("v.iter().len() = {}(ExactSizeIterator)", v.iter().len());
     11 |     let mut it = v.iter(); it.next();
     12 |     println!("消耗一个之后 len = {}", it.len());
     13 | }
  编译:成功
  运行(退出码 0):
    v.iter()                 size_hint = (5, Some(5))
    v.iter().map(..)         size_hint = (5, Some(5))
    v.iter().filter(..)      size_hint = (0, Some(5))(过滤后数量未知,下界为 0)
    v.iter().chain(v.iter()) size_hint = (10, Some(10))
    v.iter().take(2)         size_hint = (2, Some(2))
    (0..).take(3)            size_hint = (3, Some(3))
    (0..)                    size_hint = (18446744073709551615, None)(无穷)
    v.iter().len() = 5(ExactSizeIterator)
    消耗一个之后 len = 4

双端、by_ref、nth

实测 · 本机执行输出
  源码:
      1 | fn main() {
      2 |     let v = vec![1, 2, 3, 4, 5, 6];
      3 |     let mut it = v.iter();
      4 |     println!("next = {:?},next_back = {:?}", it.next(), it.next_back());
      5 |     let first_two: Vec<_> = it.by_ref().take(2).collect();      // 只消耗前 2 个,it 之后还能继续用
      6 |     println!("by_ref().take(2) = {:?};剩下 {:?}", first_two, it.collect::<Vec<_>>());
      7 |     let mut it2 = v.iter();
      8 |     println!("nth(2) = {:?},接着 next = {:?}", it2.nth(2), it2.next());
      9 |     let mut e = std::iter::empty::<i32>();
     10 |     println!("耗尽后再调用 next:{:?} {:?}", e.next(), e.next());
     11 | }
  编译:成功
  运行(退出码 0):
    next = Some(1),next_back = Some(6)
    by_ref().take(2) = [2, 3];剩下 [4, 5]
    nth(2) = Some(3),接着 next = Some(4)
    耗尽后再调用 next:None None

现成工具

实测 · 本机执行输出
  源码:
      1 | use std::iter;
      2 | fn main() {
      3 |     let mut n = 0;
      4 |     let counter: Vec<i32> = iter::from_fn(|| { n += 1; if n <= 4 { Some(n * n) } else { None } }).collect();
      5 |     println!("from_fn:{:?}", counter);
      6 |     let pows: Vec<u32> = iter::successors(Some(1u32), |&x| x.checked_mul(10)).collect();
      7 |     println!("successors(×10 直到溢出):{:?}", pows);
      8 |     let mut k = 0;
      9 |     println!("repeat_with:{:?}", iter::repeat_with(|| { k += 3; k }).take(4).collect::<Vec<_>>());
     10 |     println!("once + chain:{:?}", iter::once(0).chain(1..3).collect::<Vec<_>>());
     11 | }
  编译:成功
  运行(退出码 0):
    from_fn:[1, 4, 9, 16]
    successors(×10 直到溢出):[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]
    repeat_with:[3, 6, 9, 12]
    once + chain:[0, 1, 2]

自己实现 Iterator 见自定义 Iterator。

分步演示

Iterator
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / rustc 1.98.1(brew)/ cargo 1.98.1;单个文件用 rustc 直接编译,需要依赖时用 cargo(经代理从 crates.io 下载);计时用 std::time::Instant,数字每次运行会有小幅抖动
    • 没有验证:FusedIterator 与 fuse() 的实际作用(只在文字里说明)、size_hint 对 collect 预分配的影响、TrustedLen、Iterator::rev 对非双端迭代器的限制
    京ICP备2026067502号-1京公网安备11010502063487号