zoniony / zoniony.github.io

blog
1 stars 0 forks source link

Rust iter #14

Open zoniony opened 4 years ago

zoniony commented 4 years ago

Iter是平常用的最多了, 没事瞅瞅

迭代器模式

才了解到迭代器是一种设计模式(design pattern) ,我太菜了

遍历集合中的元素而不暴露底层实现,这里又涉及到内部迭代器和外部迭代器

可以看rust 早期拥有内部迭代器container: remove internal iterators from Map

自定义一个简单内部迭代器,内部迭代器传入元素和操作闭包之后就无法再进行操作,必须等遍历完才能够停下,中间没办法对迭代器进行操作

trait InIterator<T :Copy> {
    fn each<F: Fn(T) -> T>(&mut self, f: F);
}

impl<T: Copy> InIterator<T> for Vec<T> {
    fn each<F: Fn(T) -> T>(&mut self, f: F) {
        let mut i = 0;
        while i < self.len() {
            self[i] = f(self[i]);
            i += 1;
        }
    }
}
fn main() {
    let mut v = vec![1, 2, 3];
    v.each(|i| i * 2 );
    println!("{:?}", v);
}

现在为了更灵活,采用外部迭代器.自己自定义实现了一个外部迭代器

trait Iterator<T> {
    fn next(&mut self) -> Option<T>;
    fn current(&self) -> Option<T>;
    fn has_next(&self) -> bool;
    fn reset(&mut self);
}

struct Container<T> {
    data: Vec<T>,
}

struct ContaineIterator<'a, T> {
    idx: usize,
    container: &'a Container<T>,

}

impl<'a, T: Clone> ContaineIterator<'a, T> {
    fn new(container: &'a Container<T>) -> ContaineIterator<T> {
        ContaineIterator { idx: 0, container}
    }
}

impl<'a, T: Clone> Iterator<T> for ContaineIterator<'a, T> {
    fn next(&mut self) -> Option<T> {
        let item = self.container.data.get(self.idx).cloned();
        self.idx += 1;
        item
    }

    fn current(&self) -> Option<T> {
        self.container.data.get(self.idx).cloned()
    }

    fn has_next(&self) -> bool {
        self.container.data.len() > self.idx
    }

    fn reset(&mut self) {
        self.idx = 0;
    }
}

impl<T: Clone> Container<T> {
    fn new() -> Container<T> {
        Container {data: Vec::new() }
    }

    fn add_item(&mut self, item: T) {
        self.data.push(item);
    }

    fn iter(&self) -> impl Iterator<T> + '_ {
        ContaineIterator::new(self)
    }
}
fn main() {
    let mut c = Container::new();
    c.add_item(1);
    c.add_item(2);
    c.add_item(3);

    let mut iter = c.iter();
    let has_next = iter.has_next();
    assert_eq!(has_next, true);

    let item = iter.next();
    println!("{:?}", item);

    iter.reset();
    while iter.has_next() {
        let v = iter.next().unwrap();
        println!("item {:?}", v);
    }

    let item = iter.next();
    assert_eq!(item, None)unwarp;
    let item = iter.next();
    assert_eq!(item, None);
}

for 循环也是个外部迭代器的语法糖

fn main() {
    let v = vec![1, 2, 3];
    for i in v {
        println!("{}",i);
    }

    let v = vec![1, 2, 3];
    {
        let mut iter = v.into_iter();
        loop {
            match iter.next() {
                Some(i) => {
                    println!("{}",i);
                }
                None => break,
            }
        }
    }
}

Iterator Trait

可以看到将Iter结构说的很清楚了,通过上面自己实现的迭代器

This module is largely organized by type:

  • Traits are the core portion: these traits define what kind of iterators exist and what you can do with them. The methods of these traits are worth putting some extra study time into.
  • Functions provide some helpful ways to create some basic iterators.
  • Structs are often the return types of the various methods on this module's traits. You'll usually want to look at the method that creates the struct, rather than the struct itself. For more detail about why, see 'Implementing Iterator'.

Iterator trait 定义方法

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

    fn size_hint(&self) -> (usize, Option<usize>) { ... }
    fn count(self) -> usize { ... }
    fn last(self) -> Option<Self::Item> { ... }
    fn nth(&mut self, n: usize) -> Option<Self::Item> { ... }
    fn step_by(self, step: usize) -> StepBy<Self> { ... }
    fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
  ///.......
  ///.......

TODO

这有有点问题是关于迭代器中上界和下界的理解,数组上界和下界一样,默认迭代器长度和无限迭代器

还有reserve的理解有点没明白

IntoIterator Trait

接下来就是转换成迭代器

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

不同类型转换为Iter定一个不同的IntoIter结构体 并且被Iterator Trait 绑定,拥有next等方法

例如 Vec距离, 具体如下图

impl<T>       IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>

OIMkBp

从上面看有三种不同的迭代器

· IntoIter,转移所有权,对应self。

· Iter,获得不可变借用,对应&self。

· IterMut,获得可变借用,对应&mut self。

底下是关于数组源码中定义在impl [T]中的方法,可以看到都有统一的行为

    pub struct Iter<'a, T: 'a> {
    ptr: NonNull<T>,
    end: *const T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
    // ptr == end is a quick test for the Iterator being empty, that works
    // for both ZST and non-ZST.
    _marker: marker::PhantomData<&'a T>,
    }

    pub fn iter(&self) -> Iter<'_, T> {
        unsafe {
            let ptr = self.as_ptr();
            assume(!ptr.is_null());

            let end = if mem::size_of::<T>() == 0 {
                (ptr as *const u8).wrapping_add(self.len()) as *const T
            } else {
                ptr.add(self.len())
            };

            Iter { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: marker::PhantomData }
        }
    }

//collect::IntoIterator for &[T; _]
impl<'a, T, const N: usize> IntoIterator for &'a [T; N]
where
    [T; N]: LengthAtMost32,
{
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

迭代器适配器

可以看到还有一堆 Struct 没讲,大部分都是适配器

R2SkRj

#[must_use = "iterators are lazy and do nothing unless consumed"]表明适配器是惰性的

如果没有对迭代器产生任 何“消费”行为,它是不会发生真正的迭代的

#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Filter<I, P> {
    iter: I,
    predicate: P,
}
impl<I, P> Filter<I, P> {
    pub(super) fn new(iter: I, predicate: P) -> Filter<I, P> {
        Filter { iter, predicate }
    }
}

​ 实现也很简单,相当于传入迭代器和一个方法(闭包),表明拥有的行为,为啥是惰性的.可以理解为你虽然有这个方法,但是你得去调用才能去执行.

消费器

去使用迭代器里面的方法叫做消费器,比如 next()就是消费器,遍历迭代器里的元素.实现没啥难的= =

等以后有啥不明白的再回来补吧 (摸了