#iterator #reference #read-only #traits #debugging

iter_view

从只读引用创建迭代器

5 个版本

0.1.4 2023年2月12日
0.1.3 2023年2月12日
0.1.2 2023年2月11日
0.1.1 2023年2月11日
0.1.0 2023年2月11日

#12 in #read-only

每月 22 次下载

MIT/Apache

12KB
198

iter_view

Rust 有 IntoIterator 特性,用于从一个类型创建 IteratorIntoIterator 消耗类型,许多类型提供 iter() 方法,从不可变引用创建 Iterator 而不消耗类型。但没有为 iter() 方法提供特性。

在大多数情况下,这种特性不是必需的,因为 iter() 方法返回的 Iterator 实现了 IntoIterator 特性。但考虑以下情况


trait Inspector<T> {
    fn inspect(&self, v: &T);
}

inspect() 方法接受 T 的不可变引用,而 T 不是 Copy 类型。如果为任何对象实现 Inspector 可以转换为 Iterator,我们可以编写如下代码


impl<T, I> Inspector<T> for I
    where
        I: IntoIterator<Item = T>,
        T: std::fmt::Debug,
{
    fn inspect(&self, v: &T) {
        for item in self {
            println!("{:?}", item);
        }
    }
}

但是 IntoIterator 特性会消耗类型,编译器不会让它消失。

如果我们为切片实现 Inspector


impl<T: std::fmt::Debug> Inspector<T> for [T] {
    fn inspect(&self, v: &T) {
        for item in self {
            println!("{:?}", item);
        }
    }
}

不会工作,除非我们将 Inspector 特性修改为允许无尺寸类型


trait Inspector<T: ?Sized> {
    fn inspect(&self, v: &T);
}

无尺寸类型是有毒的,使用起来会造成很多麻烦,我们不想使用它。

Vec<T> 支持非常容易地转换为切片,但许多其他类型不支持它,例如 HashMapLinkedList,切片版本无法涵盖所有情况。

我们无法将 Iterator 传递给 inspect() 方法,因为 Iterator 是一个可变对象,而 inspect() 需要不可变引用,这使得它无法工作。

iter_view 包提供了 IterView 特性,它与 IntoIterator 类似,但它不会消耗类型


pub trait IterView<'a> {
    type Item: 'a;
    type Iter: Iterator<Item = &'a Self::Item>;
    fn iter(&'a self) -> Self::Iter;
}

使用 IterView 特性,我们可以为任何实现了 IterView 的类型实现 Inspector


impl<T, I> Inspector<T> for I
    where
        I: IterView<Item = T>,
        T: std::fmt::Debug,
{
    fn inspect(&self, v: &T) {
        for item in self.iter() {
            println!("{:?}", item);
        }
    }
}

许可证:MIT OR Apache-2.0

无运行时依赖