如何在第一次调用next()时初始化迭代器字段



我遇到了一个常见模式,其中有一个Iterator,我想在第一次调用Iteratornext()方法时初始化它的字段。我一直提出的解决方案是将该字段设为Option,并在每次调用next()时检查is_none(),如果该字段为None,则初始化该字段。

例如,假设我想创建一个名为MultFirstIterator,它采用另一个迭代器,并将第一个元素乘以所有其他元素。我不想在初始化MultFirst结构时只获取第一个元素,因为获取第一个元件可能很昂贵,而且应该在我们开始迭代MultFirst结构时完成。因此,我使用Option解决方案:

struct MultFirst<A, I: Iterator<A>> {
    first_element: A,
    iterator: I,
}
impl<A: Mul<A,A>, I: Iterator<A>> Iterator<A> for MultFirst<A,I> {
    fn next(&mut self) -> Option<A> {
        if self.first_element.is_none() {
            self.first_element = self.iterator.next()
        }
        match self.iterator.next() {
            Some(x) => Some(self.first.unwrap() * x),
            None => None
        }
    }
}

这很好,但我希望避免在每次调用next时检查is_none的性能。有什么办法我可以做到这一点吗?我在想,也许在第一次调用next之后,我可以只调用map,并以某种方式让Map结构接管对next的所有后续调用。但我不确定我是否能做到。这可能吗?或者有没有其他方法可以在不每次检查is_none的情况下完成初始化?

next方法是静态解析的,并且将始终解析为相同的函数,该函数必须实现迭代器初始化时和未初始化时的代码。您可以让struct存储next方法调用的函数指针,这将允许您通过更改函数指针来更改行为,但这将增加间接级别,并且可能比调用is_none有更多的开销。

通常,您将在迭代器的创建过程中处理初始化。如果初始化成本很高,那么不要传递迭代器,而是传递一个可用于按需创建迭代器的值。

最新更新