Infinite iterators in for

If an iterator is not statically known to be infinite, but it is, we can wrap it in some adapter like unreachable_end(iter) which replaces the end of iterator with unreachable!(). But in your examples (0..).filter(|x| *x != 10) can implement InfiniteIterator and I don't see the reason why queue one can't.

About break with value, changing map to filter_map doesn't change anything, but for example .take will make the iterator finite. In this case I can see these options:

  1. Chain with some iterator that immediately panics, or use unreachable_end(iter).
  2. Wrap the for with a labeled block (or labeled loop) and change break labels to the outer block:
let foo = 'outer: {
    for x in some_infinite_iterator.take(5) {
        if some_condition(x) { break 'outer x; }
    }
    // this case were unreachable but now it is needed
    some_default
};

Hmm, come to think of it, that could be spelled

.chain(iter::repeat_with(|| unreachable!()))

Because repeat_with is an infinite iterator, and finite.chain(infinite) is infinite.

As a PoC I implemented a crate for this: infinite_iterator - Rust

It’s based on having InfiniteIterator as a subtrait of Iterator with a next_infinite method. It provides an ifor! macro as a superset of the for…in syntax, automatically supporting break-with-value for InfiniteIterators and normal break for regular Iterators (via inherent method specialization). I didn’t go with a blanket impl to allow the case of types like Map.

3 Likes

Generalising iterators to generators (that aside from a normal yielding type, have a ā€˜final’ return type) might solve this issue and more:

Inexhaustible iterators could be simply expressed as Generator<Return=!>.

Nice generalization, though I'm not a fan of exhausted or else block. I prefer returning generator result directly. It would make examples in my original post work as is (without special casing ! type) and type system would understand that codes after infinite for loops are unreachable (which you mentioned it as a drawback? The section about returning generator values and ! type looks wrong to me, I think break num example should work since ! can be casted to any type). Some adapters for generators (as you mentioned) and iterators for converting them to generators can do the job of exhausted block.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.