写解析器经常需要「看一眼下一个元素再决定」,调试迭代器链又需要「看一眼中间的值」。Peekable 和 inspect 分别解决这两件事。这篇用计数器验证 peek 的真实行为,用词法分析对比 take_while,并用 inspect 看清链的执行顺序。
编译:成功
运行(退出码 0):
刚创建:源已产出 0 个
peek -> Some(1),源已产出 1 个
再 peek -> Some(1),源已产出 1 个(没有再拉)
next -> Some(1),源已产出 1 个(返回的是缓存的 1)
next -> Some(2),源已产出 2 个
peek_mut 改成 99: Some(99)
size_of Peekable<Range<i32>> = 16 字节(Range 本身 8) 源码:
1 | fn main() {
2 | let mut it = [1, 2, 3].iter().peekable();
3 | let first = it.peek().unwrap();
4 | it.next();
5 | println!("{}", first);
6 | }
编译:失败
error[E0499]: cannot borrow `it` as mutable more than once at a time
--> <实验目录>/src/u66b.rs:4:5
|
3 | let first = it.peek().unwrap();
| -- first mutable borrow occurs here
4 | it.next();
| ^^ second mutable borrow occurs here
5 | println!("{}", first);
| ----- first borrow later used here
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0499`. 编译:成功
运行(退出码 0):
peekable + next_if: ["12", "+", "345", "*", "6"]
take_while 读第一个数字 "12",剩余 "345*6"(分隔符 '+' 已经被丢掉)
next_if_eq(&'a') -> Some('a') next_if_eq(&'z') -> None 剩余 "b"iterator 的惰性见Iterator 的惰性执行。
源码:
1 | fn main() {
2 | let r: Vec<i32> = (1..=5)
3 | .inspect(|x| println!(" [源] {}", x))
4 | .filter(|x| x % 2 == 1)
5 | .inspect(|x| println!(" [filter 之后] {}", x))
6 | .map(|x| x * x)
7 | .inspect(|x| println!(" [map 之后] {}", x))
8 | .collect();
9 | println!("结果 {:?}", r);
10 | let s: i32 = [1, 2, 3].iter().inspect(|x| print!("{} ", x)).sum();
11 | println!("sum = {}(inspect 的参数是 &Item,不能修改元素)", s);
12 | }
编译:成功
运行(退出码 0):
[源] 1
[filter 之后] 1
[map 之后] 1
[源] 2
[源] 3
[filter 之后] 3
[map 之后] 9
[源] 4
[源] 5
[filter 之后] 5
[map 之后] 25
结果 [1, 9, 25]
1 2 3 sum = 6(inspect 的参数是 &Item,不能修改元素)
源码:
1 | fn main() {
2 | let v: Vec<i32> = [1, 2, 3].iter().inspect(|x| **x += 1).copied().collect();
3 | println!("{:?}", v);
4 | }
编译:失败
error[E0594]: cannot assign to `**x`, which is behind a `&` reference
--> <实验目录>/src/u66e.rs:2:52
|
2 | let v: Vec<i32> = [1, 2, 3].iter().inspect(|x| **x += 1).copied().collect();
| ^^^^^^^^ cannot assign
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0594`.dbg! 宏本身见dbg! 宏的实现方式。