S Salted的笔记
Tab折叠当前
Shift+Tab全局折叠
/搜索
点击圆点折叠

iterator

更新2026-06-19 章节0
  for x in vec!["a","b","c"]/*.into_iter()*/ {
      //    ...
  }

desuger :

  let iter = vec!["a","b","c"].into_iter() ;
  while let Some(ele) = iter.next() {
      // ... 
  }

为何将类型定义作为trait的一个字段?

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>; 
    // ... 
}

而不写成泛型参数的形式 :

trait Iterator<Item>
{
    fn next(&mut selt) -> Option<Item> ;
    // ... 
}

因为我们想使对每个类型 (eg Vec<T>) 只实现一个Iterator trait. 而不是分别出现: Iterator<i32> , Iterator<u64>, ... . 而作为泛型参数则在语法上使得能为一个struct实现impl多个 Iterator<T> trait .

( 这里的trait有点像OCaml中的module struct/signature )

其根本原因在于迭代器的功能在于按照一定顺序遍历元素. 而这个功能不会因为类型Item的不同而发生变化. ( 功能逻辑是否会因为具体类型的不同而发生变化 )

相反地, 有个不能用第一种形式的例子:

trait Service<Request> {
    fn do(&mut self, r: Request) ; 
} 

类型request在这里不能作为成员, 而是要作为泛型参数.

因为不同的Request对应的处理函数do()的逻辑不同, 为了能对同一个struct多次分别实现不同的trait, 这里要将其作为泛型参数.

let vs = vec![1,2,3,4];

for e in vs {
    // consumes vs, owned e.
}
for e in vs.iter() {
    // borrows vs, v is a reference. 
}
for e in &vs {
    // equivalent to vs.iter().
}

rust trait Iterator { type Item; // ...... fn flatten(self) -> Flatten<Self> where Self::Item : IntoIterator {/*...*/} }

image-20220807211619922

let vec = vec![vec![1,3,5],vec![2,4,6]] ;
let f = vec.into_iter().flatten().collect::<Vec<u8>>();
assert_eq!(f, &[1,3,5,2,4,6]); 

在flatten的声明中要求迭代器中的Item必须实现了IntoIterator, 这点结合例子就很容易理解, 在这里每一项是一个vec, 因此必须有能力对每个元素本身进行遍历, 因此自然要求Item实现了某种迭代器trait.

IntoIterator是将容器转换为迭代器的trait. (而不是通过借用导出一个迭代器: .iter()/.iter_mut() ), 其重点是如何实现转换函数: into_iter(self)

trait IntoIterator{
    type Item;
    type IntoIter: Iterator<Item= Self::Item>;
    fn into_iter(self) -> Self::IntoIter ;
}

其trait只有三个成员.