为什么Iterator :: next返回一个Option而不仅仅是一个项目?

tho*_*dge 1 iterator rust

在我看来,一个选项是否是正确的返回类型应由实现者决定.

我注意到当我尝试过滤或使用项目上的其他收集方法时它会消失.这只是一个替代品has_next吗?它不会有潜在的性能/内存影响吗?

DK.*_*DK. 7

因为需要某种方式与调用者进行通信,所以没有什么可以输出的.

fn main() {
    let mut it = vec![1, 2, 3].into_iter();
    assert_eq!(it.next(), Some(1));
    assert_eq!(it.next(), Some(2));
    assert_eq!(it.next(), Some(3));
    assert_eq!(it.next(), None); // End of iterator.
}
Run Code Online (Sandbox Code Playgroud)

至于假设has_next,这会使一些迭代器设计复杂化,因为它需要迭代器来知道是否还有其他元素.这可能需要迭代器来计算下一个元素,然后将其存储在某个地方.也可能忘记打电话has_next或打电话但忽略结果.

随着next回国的Option,这一切都不是一个问题; 迭代器可以计算下一个项目并返回它,同时使调用者无法忘记确保返回的值实际上有内容.

这件事不能让你做的是"窥视"迭代器,看看是否有更多东西,然后根据答案改变逻辑,而不实际消耗下一个项目.然而,这就是peekable组合器的用途,它为您提供了传统的东西has_next:peek().is_some().

关于你对表现的担忧:我从来没有看到任何暗示有任何惩罚的事情.任何正确使用迭代器的东西必须检查它是否到达终点.至于空间,Rust迭代器不需要缓存下一个项目,因此它们可能与使用的语言的迭代器大小相同或更小has_next.

最后,如注释中所述,Option不是堆分配的.A None相当于a false后跟一些未初始化的空间(因为其中没有任何内容),a Some(v)等效于a true后跟v.

  • @thoredge:如果你使用`has_next`,你将创建尽可能多的`bool`s,因为你有字节. (4认同)
  • @thoredge 一个 `Option<i32>` 本质上(就布局而言)是一个 `(bool, i32)` 元组。“bool”和“i32”可能会在寄存器中返回,但大于“i32”的东西可能会保留在调用者的堆栈上并直接写入那里;[这个问题](/sf/ask/1948476281/)有更多信息。 (2认同)
  • @thoredge:此外,如果“Option<T>”中的“T”是一种永远不会具有全零位模式的类型,[编译器可以完全优化标记](https://stackoverflow. com/questions/46557608/what-is-the-null-pointer-optimization-in-rust)。例如,“Option<&Foo>”与“&Foo”大小相同。 (2认同)