You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 迭代器
## 错误一
一般情况下可以用过iter.map().rev()对一个迭代器进行连续变换,但是有些特殊场景,我们需要这样的形式:
```rust
let iter = array.to_iter();
iter = iter.map();
iter = iter.rev();
```
是的,这种用法很不常见,但是一旦遇到,那么编译检查将是你难以通过的天堑,例如以下代码:
```rust
fn main() {
let arr = [0u32; 100]; // big array or vector with random numbers
let mut iter= arr.iter();
let map_func: Option<fn(&u32) -> &u32> = None;
let reverse = true;
if let Some(closure) = map_func {
iter = iter.map(closure);
}
if reverse {
iter = iter.rev();
}
// many more modification...
let list: Vec<&u32> = iter.collect();
println!("{:?}", list);
}
```
运行后,产生报错:
```console
error[E0308]: mismatched types
--> src/main.rs:8:14
|
8 | iter = iter.map(closure);
| ^^^^^^^^^^^^^^^^^ expected struct `std::slice::Iter`, found struct `Map`
|
= note: expected struct `std::slice::Iter<'_, _>`
found struct `Map<std::slice::Iter<'_, _>, for<'r> fn(&'r u32) -> &'r u32>`
error[E0308]: mismatched types
--> src/main.rs:12:14
|
12 | iter = iter.rev();
| ^^^^^^^^^^ expected struct `std::slice::Iter`, found struct `Rev`
|
= note: expected struct `std::slice::Iter<'_, _>`
found struct `Rev<std::slice::Iter<'_, _>>`
```
原因很简单,`let mut iter= arr.iter()`这里生成的`iter`是`std::slice::Iter`类型,但是`iter.map()`生成的是`Map<std::slice::Iter<'_, _>>`类型,因此无法进行直接赋值,`iter.rev()`也是类似情况。
那么为什么我们可以这样使用: `iter.map().rev()`?,因为`Map<std::slice::Iter<'_, _>>`实现了`Iterator`特征,因此可以直接在其上调用`rev`这个属于`Iterator`的方法。
回到上面的问题,因为`std::slice::Iter` 和 `Map<std::slice::Iter<'_, _>>`都实现了`impl Iterator<Item=T>`的特征,因此我们可以考虑用一个`Box<dyn Iterator<Item=u32>>`的类型来对iter进行包裹:
```rust
fn main() {
let arr = [0u32; 100]; // big array or vector with random numbers
let mut iter: Box<dyn DoubleEndedIterator<Item=&u32>> = Box::new(arr.iter());
let map_func: Option<fn(&u32) -> &u32> = None;
let reverse = true;
if let Some(closure) = map_func {
iter = Box::new(iter.map(closure));
}
if reverse {
iter = Box::new(iter.rev());
}
// many more modification...
let list: Vec<&u32> = iter.collect();
println!("{:?}", list);
}
```
Bingo代码编译通过!