【问题标题】:Why does Iterator::next return an Option instead of just an item?为什么 Iterator::next 返回一个选项而不仅仅是一个项目?
【发布时间】:2018-11-04 19:41:37
【问题描述】:

在我看来,一个选项是否是正确的返回类型应该取决于实现者。

我注意到当我尝试过滤或对项目使用其他收集方法时,它会消失。这仅仅是has_next 的替代品吗?它不会对性能/内存产生潜在影响吗?

【问题讨论】:

  • [].iter().next() 应该怎么做?
  • “它不会有潜在的性能/内存影响吗?”没有更多的任何
  • @trentcl 我想这是 Rust 中的一个优先事项,以避免对耗尽的迭代器产生恐慌。其他语言使用 has_next 然后在 next 上恐慌。在一个相当低级的结构上,这感觉就像是一个很大的开销。
  • @Stargateur 如果您在字节 (u8) 上创建迭代器,您将创建尽可能多的 Somes 有字节。
  • @thoredge 不,每次 一个 条目最多额外增加 8 个字节(通常甚至 0 个字节);移动到下一个 Item 删除前一个。

标签: iterator rust


【解决方案1】:

因为它需要 某种 方式来与调用者沟通没有什么可输出的。

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.
}

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

next 返回一个Option,这都不是问题;迭代器可以计算下一项并将其返回,同时使调用者不可能忘记确保返回的值实际上包含某些内容。

让你做的一件事是“窥视”迭代器以查看是否还有更多内容,然后根据该答案更改逻辑,没有实际消耗下一项。但是,这就是 peekable 组合器的用途,它为您提供相当于传统的 has_next: peek().is_some()

关于您对性能的担忧:我从未见过任何迹象表明存在任何惩罚。任何正确使用迭代器的东西必须检查它是否已经到达末尾。至于空间,Rust 迭代器不需要缓存下一项,因此它们可能与使用 has_next 的语言的迭代器大小相同或更小。

最后,如 cmets 中所述,Option 未分配堆。 None 相当于 false 后跟一些未初始化的空间(因为里面没有任何内容),Some(v) 相当于 true 后跟 v

【讨论】:

  • 我的意思是,这感觉是一种非常昂贵的方式。如果你在字节(u8)上创建一个迭代器,你将创建尽可能多的 Somes 有你有字节。
  • @thoredge:如果您使用has_next,您将创建与字节数一样多的bools。
  • @thoredge:等一下,你是不是觉得Option是堆分配的?
  • @thoredge 一个Option<i32> 本质上(就布局而言)是一个(bool, i32) 元组。 booli32 可能会在寄存器中返回,但大于 i32 的内容可能会保留在调用者的堆栈中并直接写入那里; this question 有更多信息。
  • @thoredge:另外,如果Option<T> 中的T 是一种永远不会有全零位模式的类型,the compiler can optimize the tag out entirely。例如,Option<&Foo>&Foo 的大小相同。
猜你喜欢
  • 1970-01-01
  • 2016-08-04
  • 2017-08-11
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多