「迭代器是惰性的」这句话该怎么验证?这篇用带 println 的闭包、计数器和 size_of,把「不消费不执行」「逐个元素穿过整条链」「短路后源不再产出」「链只是一个小结构体」都直接测出来。
源码:
1 | fn main() {
2 | let v = vec![1, 2, 3];
3 | v.iter().map(|x| { println!("闭包执行了 x={}", x); x * 2 });
4 | println!("上一行之后,没有任何「闭包执行了」输出");
5 | }
编译:成功;警告:
warning: unused `Map` that must be used
--> <实验目录>/src/u62a.rs:3:5
|
3 | v.iter().map(|x| { println!("闭包执行了 x={}", x); x * 2 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: iterators are lazy and do nothing unless consumed
= note: `#[warn(unused_must_use)]` (part of `#[warn(unused)]`) on by default
help: use `let _ = ...` to ignore the resulting value
|
3 | let _ = v.iter().map(|x| { println!("闭包执行了 x={}", x); x * 2 });
| +++++++
warning: 1 warning emitted
运行(退出码 0):
上一行之后,没有任何「闭包执行了」输出 源码:
1 | fn main() {
2 | let r: Vec<i32> = (1..=4)
3 | .inspect(|x| println!(" 源 产出 {}", x))
4 | .filter(|x| { let keep = x % 2 == 0; println!(" filter {} -> {}", x, keep); keep })
5 | .map(|x| { println!(" map {} -> {}", x, x * 10); x * 10 })
6 | .collect();
7 | println!("结果 {:?}", r);
8 | }
编译:成功
运行(退出码 0):
源 产出 1
filter 1 -> false
源 产出 2
filter 2 -> true
map 2 -> 20
源 产出 3
filter 3 -> false
源 产出 4
filter 4 -> true
map 4 -> 40
结果 [20, 40]Iterator 的基本协议见Iterator Trait。
编译:成功
运行(退出码 0):
filter(%3==0).take(3) = [3, 6, 9] 源总共产出 9 个
find(==7) = Some(7) 源总共产出 7 个
any(>100) = true 源总共产出 101 个
take(5).count() = 5 源总共产出 5 个
take_while(<4).sum() = 6 源总共产出 4 个(多产出一个用来发现 4 不满足条件) 编译:成功
运行(退出码 0):
无穷序列取前 5 个偶数的平方: [4, 16, 36, 64, 100]
类型: map::Map<filter::Filter<Range<i32>, u62d::main::{{closure}}>, u62d::main::{{closure}}>
size_of(这条链) = 12 字节(Range<i32> 本身 8 字节;闭包 filter 无捕获、map 捕获了 k)
在 100 万元素 Vec 上建一条 map+filter 链: size_of = 16 字节(只存了迭代器状态,不存元素)自定义适配器见自定义 Iterator。
源码:
1 | fn main() {
2 | let it;
3 | {
4 | let v = vec![1, 2, 3];
5 | it = v.iter().map(|x| x * 2);
6 | }
7 | println!("{:?}", it.collect::<Vec<_>>());
8 | }
编译:失败
error[E0597]: `v` does not live long enough
--> <实验目录>/src/u62e.rs:5:14
|
4 | let v = vec![1, 2, 3];
| - binding `v` declared here
5 | it = v.iter().map(|x| x * 2);
| ^ borrowed value does not live long enough
6 | }
| - `v` dropped here while still borrowed
7 | println!("{:?}", it.collect::<Vec<_>>());
| -- borrow later used here
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0597`.
编译:成功
运行(退出码 0):
建好链之后 log = (此时不能读,因为闭包还借着 log)
消费之后 log = [1, 2, 3]