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.

2.6 KiB

迭代器

错误一

一般情况下可以用过iter.map().rev()对一个迭代器进行连续变换,但是有些特殊场景,我们需要这样的形式:

let iter = array.to_iter();
iter = iter.map();
iter = iter.rev();

是的,这种用法很不常见,但是一旦遇到,那么编译检查将是你难以通过的天堑,例如以下代码:

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);
}

运行后,产生报错:

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()这里生成的iterstd::slice::Iter类型,但是iter.map()生成的是Map<std::slice::Iter<'_, _>>类型,因此无法进行直接赋值,iter.rev()也是类似情况。

那么为什么我们可以这样使用: iter.map().rev()?,因为Map<std::slice::Iter<'_, _>>实现了Iterator特征,因此可以直接在其上调用rev这个属于Iterator的方法。

回到上面的问题,因为std::slice::IterMap<std::slice::Iter<'_, _>>都实现了impl Iterator<Item=T>的特征,因此我们可以考虑用一个Box<dyn Iterator<Item=u32>>的类型来对iter进行包裹:

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代码编译通过!