But…take doesn’t know the base iterator is infinite. (That is, we don’t have a trait for that.)
There's a couple of places where it'd be nice to have one, though.
For example, an InfiniteIterator::next_infinite -> Self::Item
wouldn't need the Option
wrapper, and we could always offer converting an infinite iterator into an array because it resolves how to handle the "error" cases that happen for finite iterators.
See ACP: Uplift `iter::repeat_n` from itertools · Issue #120 · rust-lang/libs-team · GitHub that also talked (in alternatives) about the possibility of adding an infinite iterator trait that would let Take
be ESI
here.
Or here's a previous conversation about how zip
ping with an infinite iterator would also be nice https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Improving.20TrustedRandomAccess.20and.20its.20Zip.20specialization/near/238965863.
Hang on, what is an "infinite iterator"? One that guarantees that next
will never return None
? Because of course you can keep calling next
on every iterator and, unless it's a FusedIterator
, it might eventually return Some
again.
There's probably a clearer name to be bikeshed for this than "infinite".
Yes, that's exactly what it means. Things like repeat(0)
or (0..).into_iter()
or repeat_with(rand)
, which will never return None
and thus should have size_hint
of (usize::MAX, None)
.
(Note that repeat(0).map(|_| panic!())
is still infinite, because it can't return None
. And that's important for getting derived size_hint
s right, as in RangeFrom should have an infinite size_hint by scottmcm · Pull Request #42315 · rust-lang/rust · GitHub )
If we ever get pattern types or similar, and trait method refinement in subtraits, then we could perhaps have InfiniteIterator::next(&mut self) -> Option<Self::Item is Some>
(even without subtrait refinement, if we get refined impls, all infinite iterator types could still opt-in to the refined return type)
That would be nice, but it might not be quite enough. Part of the problem I encountered in Improve the `array::map` codegen by scottmcm · Pull Request #107634 · rust-lang/rust · GitHub was that Ok(foo).unwrap()
didn't completely optimize out when it's cross-function and a large foo
(like a long array of u32
) because the Result
(or, here, Option
) ends up bigger than the inner value and thus there's some memcpy
ing that doesn't get removed. (See also issues like Using ManuallyDrop causes allocas and memcpys that LLVM cannot remove · Issue #79914 · rust-lang/rust · GitHub)
So, unfortunately, for now at least there's still value in things that don't wrap stuff up into enums, like why https://stdrs.dev/nightly/x86_64-unknown-linux-gnu/core/iter/traits/unchecked_iterator/trait.UncheckedIterator.html#method.next_unchecked exists inside libcore.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.