<p>Many high-level languages have some kind of protocol or interface for <a href="https://en.wikipedia.org/wiki/Iterator" rel="noreferrer">iterators</a>, allowing user-defined types to be used in &quot;for-each&quot; loops. A few examples from popular languages:</p>
<ul>
<li>In Java, a class which implements the <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html" rel="noreferrer"><code>Iterator&lt;E&gt;</code></a> interface must provide a <code>hasNext()</code> method to indicate whether the iteration should continue, and a <code>next()</code> method to return the next iterated element. Additionally, there is an optional <code>remove()</code> method to remove the element previously returned by <code>next()</code> from the underlying collection.</li>
<li>In Javascript, an object implements the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol" rel="noreferrer">iterator protocol</a> by providing a <code>next()</code> method returning an object with a <code>value</code> property for the iterated element, and a <code>done</code> property indicating whether the iterator is exhausted. (When <code>done</code> is true, <code>value</code> is not required.)</li>
<li>In Python, a class can be <a href="https://docs.python.org/3/glossary.html#term-iterable" rel="noreferrer">iterable</a> in two ways:
<ul>
<li>It can have a <code>__len__</code> method and a <code>__getitem__</code> method to represent an <a href="https://docs.python.org/3/glossary.html#term-sequence" rel="noreferrer">iterable sequence</a>, where each element can be accessed by index;</li>
<li>It can have an <code>__iter__</code> method returning an <a href="https://docs.python.org/3/glossary.html#term-iterator" rel="noreferrer">iterator</a> object, which provides a <code>__next__</code> method. When this method is called, it either returns the next iterated element, or it raises the special exception <code>StopIteration</code> to indicate that the iterator is exhausted.</li>
</ul>
</li>
</ul>
<p>These protocols differ in the methods that the object must provide, and the expected behaviour of those methods. What are the advantages and disadvantages of these designs, or of other iteration protocols from other languages?</p>

<design-choice-comparison><iterators>
Advantages and disadvantages of different iterator protocols
CC BY-SA 4.0
2023-05-30T16:00:11.933Z
Rust's is similar to Java's except it uses an Option instead of hasNext
Seggan
CC BY-SA 4.0
2023-05-30T16:02:14.850Z
@Seggan I'd say that makes it more similar to Javascript's ─ it returns a kind of wrapped value which holds both the iterated value and the termination condition. However, Javascript's protocol also allows for `{value: 23, done: true}` to indicate a return value from a generator.
kaya3
CC BY-SA 4.0
2023-05-30T16:06:50.000Z
Haskell's `Foldable` might be another approach worth noting--not that it actually supports imperative for-loops, but the general idea is certainly applicable: rather than provide hooks for a for-loop to iterate with, the type provides the entire loop construct itself.
Unrelated String
CC BY-SA 4.0
2023-05-30T16:12:01.297Z
C#’s `IEnumerator<T>` has `bool MoveNext()` and `T Current`, as well as an optional `void Reset()` to support restarting mid-iteration.
Bbrk24
<h2>Java</h2>
<ul>
<li>a separate <code>next</code> and <code>hasNext</code> method is inconvenient to implement, but nice for users
<ul>
<li>In many cases it might be actually impossible to implement <code>hasNext</code>. Consider the case where you have a iterator representing some data downloaded over the internet. You never know when the other side is going to stop sending.</li>
<li>On the other hand, this gives users information that would be impossible to receive otherwise. While a peek adapter can tell you this info it would consume one extra step from the iterator and if that causes side effects it could be undesirable.</li>
<li>A hasNext method allows very egronomic looping in a <code>for(;;)</code> c-style for loop, if your language lacks a <code>foreach</code> equivalent this might be a important feature.</li>
</ul>
</li>
<li>A <code>remove</code> method is quite useful since removing things from iterators while iterating is famously hard, but it's also only useful for some very specific types of iterators so it's weird to have it as part of a interface, even when optional.</li>
<li>There is no protection from advancing past the end of the iterator</li>
</ul>
<h2>Javascript</h2>
<p>The main downside of Javascript iterators is the limited amount of functions and tooling that supports them, not the interface itself.</p>
<p>The downside of returning both next and done is that it's easy to keep iterating by accident after the end and a type checker won't be able to detect this. If your language has the equivalent of <code>#[must_use]</code> to warn about not using a value, that risk could be avoided. JS does not though.</p>
<h2>Python</h2>
<p>As pppery said the &quot;old-style&quot; python iterators are quite confusing and often lead to things unintentionally being iterators but then not actually working as iterators.</p>
<p>Raising a exception on error is very verbose to deal with compared to just checking a boolean. On the other hand it's impossible to forget to check which is nice.</p>
<h2>Rust</h2>
<p>In rust iterators impelement a trait, <code>iter.next()</code> returns a <code>Option&lt;T&gt;</code>. This is nice because you are forced to check if you have reached the end and can't cause bugs.</p>
<p>Iterator convenience method are implemented on the trait itself which leads to a nice chaining syntax in reading order, unlike python where you need to nest functions leading to a &quot;in to out&quot; execution order.</p>
<p>Iterables in rust are requied to implement <code>into_iter()</code> but in practice most implement <code>iter()</code> too which doesn't consume the reference so is usually preferred. Many implement other alternative methods too like <code>.iter_mut()</code>. The many ways to convert things into iterators is is confusing.</p>

CC BY-SA 4.0
2023-05-30T16:22:04.007Z
2023-12-20T17:01:03.330Z
2023-12-20T17:01:03.330Z
mousetail 'he-him'
CC BY-SA 4.0
2023-05-30T16:28:47.430Z
This is a good answer, although it focuses mostly on the consumer's side of the protocol (i.e. how to consume an iterable/iterator, if you aren't just using the language's built-in `for` loop that handles things). I suppose that is still important since for some use-cases you do have to consume iterators in user-written code. Nonetheless, I think the implementor's side of the protocol is probably more significant from a usability perspective, since it's more common to have to make a user-defined type iterable.
kaya3
CC BY-SA 4.0
2023-05-30T16:29:56.070Z
@kaya3 If you just use the built in iterators in a built in for each loop it doesn't really matter how the protocol is defined since the details will be handled for you
mousetail 'he-him'
CC BY-SA 4.0
2023-05-30T16:40:15.880Z
My point is not about built-in iterators, it's about implementing the iteration protocol on a user-defined type, and that being a more common task than having to manually consume an iterator. That said, even when using only built-in iterators for built-in types in a `for` loop, there may be performance considerations between the different protocol designs.
kaya3
CC BY-SA 4.0
2023-05-30T16:42:46.377Z
Swift is similar to Rust except that its equivalent to `into_iter` doesn’t invalidate the original object — in practice that usually means it just bumps the refcount, since all the builtin collection types are CoW.
Bbrk24
CC BY-SA 4.0
2023-05-30T20:28:41.523Z
@kaya3 True, there is just not much to say about the difference in implementation for returning a special object or raising a exception. It only really matters for the users of the API. Only Java really has unique features that effect implementors
mousetail 'he-him'
CC BY-SA 4.0
2023-12-21T19:04:14.717Z
"A hasNext method allows very egronomic looping in a for(;;) c-style for loop, if your language lacks a foreach equivalent" - It's hard to imagine why a language that requires `for(;;)` style looping would implement an iterator protocol. I think it's literally only C++ that does this, and there it's simpler to use since the equivalent of `hasNext` is basically conversion to boolean (and the equivalent of `next` is an overloaded pointer-dereference operator).
Karl Knechtel
<ol>
<li>The first Python syntax has the advantage that custom list-like objects become iterable automatically without the user thinking about it.</li>
<li>Conversely, the first Python syntax has the disadvantage that it's a heruistic that sometimes isn't correct - if you are implementing a custom dictionary-like object then it will have a <code>__getitem__</code> and a <code>__len__</code>, but synthesizing them won't produce a useful iterator.</li>
<li>Obviously, the Java syntax supports a <code>remove</code> method that no other language does, which could be said to be an advantage, as removing elements from the list while iterating it is a common pain point. It also makes it clear that that operation may not be supported if it doesn't make sense.</li>
<li>The Java syntax has the disadvantage that it requires the iterator to know whether there is a next element without producing it, which may not be possible for some iterators (think a Python generator - you never know whether it will yield another value or return before running the code). While you can of course work around this by calculating the next value in <code>hasNext</code>, that's counterintuitive and confusing.</li>
</ol>

CC BY-SA 4.0
2023-05-30T16:08:56.740Z
2023-05-30T16:08:56.740Z
pppery
<p>A commonly-cited argument against Python's approach, where the <code>StopIteration</code> exception indicates that an iterator is exhausted, is that raising and catching an exception is typically slower than returning a value and checking it with an <code>if</code> statement. However, <a href="https://stackoverflow.com/a/20116881/12299000">this is not true in CPython</a>, since the CPython interpreter handles <code>StopIteration</code> as a special case in order to make iteration fast. So this is more of an implementation concern than a design concern.</p>
<hr />
<p>Nonetheless, this approach does have a specific pitfall, which is that it allows for non-local control flow effects. This usually only happens by accident, but it's hard to reason about so it can cause bugs which are difficult to diagnose. The issue occurs when <code>StopIteration</code> is thrown indirectly by something a <code>__next__</code> method calls, rather than intentionally by the <code>__next__</code> method itself. In this case, the <code>StopIteration</code> exception bubbles up and is caught by whatever consumes the iterator; the consumer then thinks the iterator is exhausted when it isn't necessarily. An example of this occurring &quot;in the wild&quot; is given in <a href="https://stackoverflow.com/q/71351209/12299000">this Stack Overflow Q&amp;A</a>.</p>
<p>The protocol could be changed slightly to prevent this: each iterator could have its own sentinel exception, provided by the consumer, so that the consumer knows it can only be thrown by that specific iterator. However, it would make the protocol more complicated to implement, which doesn't seem worth it to address a pitfall that only occurs very rarely.</p>
<p>The other approaches, which use the return value of the <code>next</code> or <code>hasNext</code> method to signal termination, don't have this problem because unlike exceptions, return values cannot have non-local control flow effects that automatically bubble up the stack.</p>

CC BY-SA 4.0
2023-05-30T17:03:19.247Z
2023-05-30T17:34:26.330Z
2023-05-30T17:34:26.330Z
kaya3
<p>The language*<sup>1</sup> which has the best possible iterators is, in my opinion, C#. I will explain why.</p>
<ol>
<li><p>The collection to be iterated does not have to implement any particular interface. All standard collections implement <code>IEnumerable</code>, but that is not necessary: if the collection has a <code>IEnumerator&lt;T&gt; GetEnumerator()</code> function, it is eligible for participation in a <code>foreach</code> loop.</p>
</li>
<li><p>If the <code>IEnumerator</code> returned by <code>GetEnumerator()</code> is disposable, then at the end of the <code>foreach</code> loop the disposable will be disposed. Contrast this with Java, where the programmer has to be aware of, and explicitly dispose, any <code>Iterator</code> that happens to be <code>Closeable</code>.</p>
</li>
<li><p>The functions offered by <code>IEnumerator</code> are <code>bool HasNext()</code>, <code>void MoveNext()</code>, and <code>T Current</code> (a property.) Thus, if you want access to the <code>IEnumerator</code> you can refrain from using a <code>foreach</code> loop, and you can use a regular <code>for</code> loop instead, where the initialization clause of the <code>for</code> loop creates the enumerator, the condition clause invokes <code>HasNext()</code>, the step clause invokes <code>MoveNext()</code>, and the current value is at any moment available via the <code>Current</code> property, which you can invoke multiple times in the same iteration if you need to.</p>
</li>
<li><p>This makes it very easy to create <em><strong>decorators</strong></em> of <code>IEnumerator</code>. (<a href="https://en.wikipedia.org/wiki/Decorator_pattern" rel="nofollow noreferrer">wikipedia</a>) Contrast this to Java, where the functions offered by <code>Iterator</code> cannot easily be used in a regular <code>for</code> loop, and decorators are really hard to write. A filtering iterator cannot be implemented without cumbersome look-ahead logic, and then it is impossible to use it for removing items from the collection because looking ahead means that you are always past the item you want to delete.</p>
</li>
</ol>
<hr />
<p>*<sup>1</sup> I only consider strongly typed languages. Weakly typed languages like Javascript, Python, etc. receive nothing but scorn from me.</p>

CC BY-SA 4.0
2023-12-20T17:46:27.410Z
2023-12-20T17:46:27.410Z
Mike Nakis
CC BY-SA 4.0
2023-12-21T08:04:58.567Z
You hate weakly typed languages yet praise duck typing features in C#, ironic
mousetail 'he-him'
<h2>Multiple return</h2>
<p>If a language supports returning multiple values in functions or methods, a somewhat better protocol is the generator to return <code>(live: bool, ref data: T?)</code>, where <code>live</code> indicates that the enumerator reader should examine the data or keep running, and <code>data</code> is an <code>Optional&lt;T&gt;</code> that indicates if any data is produced in this iteration.</p>
<p>This protocol would cover both direct and async usage, and would further permit filter dropping or accumulating usage in direct code.</p>
<h2>Ref return</h2>
<p>The <code>ref data</code> instead of simple <code>data</code> is designed to reduce allocation of temporaries drastically in enumerations. To zero, in special.</p>
<p>Other protocols may cause unnecessary allocations by preserving the <code>next</code> data in a backing field, after running/returning of <code>hasMext</code>, and would otherwise impossibilite the creation of generators of &quot;stack only&quot; data types.</p>
<p>The language may offer composite, possible allocating <code>IteratorResult&lt;T&gt;</code> that conforms to Java/C# protocol, that buffers the results outside the generator, instead of forcing the existence of storage by design.</p>
<h2>Normal syntax</h2>
<p>With or without multiple returns, I also argue that a big step in easing the creation and usage of generators and iterations is to make their syntax simple, instead of special.</p>
<p>A generator is basically an async function that returns multiple times. The same with iterators.</p>
<p>A simple syntax for this wuuld be, for example, and taking note from languages that names the <code>Optional&lt;T&gt;</code> cases with <code>None</code> and <code>Some&lt;T&gt;</code>, to mark generator and/or iterator functions with returning <code>Many&lt;T&gt;</code></p>
<pre class="lang-cs prettyprint-override"><code>public async Many&lt;T&gt; Filter( Predicate pred )
{ }
</code></pre>

CC BY-SA 4.0
2023-12-20T19:36:11.597Z
2023-12-20T19:36:11.597Z
André L F S Bacci
<p>The iteration protocols in the question all rely on <em>mutable</em> iterators: Each iteration has a <em>single</em> iterator object on which a <code>.next</code> method is called for each step; the iterator must mutate its state between <code>.next</code> calls to advance.</p>
<p>An example that also allows immutable iterators is the <a href="https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration" rel="nofollow noreferrer">Julia iterator interface</a>. This is realised by each iteration step providing a <code>state</code> in addition to a <code>value</code>:</p>
<ul>
<li><code>iterate(iterable)</code> starts iteration by producing a new <code>state</code></li>
<li><code>iterate(iterable, state)</code> resumes iteration from the previous <code>state</code></li>
</ul>
<p>By passing the <code>state</code> into each iteration step and receiving the next <code>state</code>, <code>state</code> may be newly created on each step and thus be immutable.</p>
<p>There are some advantages to this:</p>
<ul>
<li>This protocol is still compatible with mutable iteration as <code>iterate</code> is free to mutate and pass back the <code>state</code> it got or to mutate <code>iterable</code>.</li>
<li>For immutable <code>iterable</code> and <code>state</code>, the tuple of <code>(iterable, state)</code> clearly defines a point in the iteration. This makes it simple and safe to split one iterator into two or more at any point, or to safe an earlier state to roll back to it.</li>
<li>The end-of-iteration can be clearly marked by returning the sentinel value <code>nothing</code> instead of a tuple. This makes it impossible to accidentally proceed with iteration past the end, yet allows the sentinel to still be a valid value as <code>(nothing, state)</code>.</li>
</ul>
<p>The added complexity of lugging around both <code>iterable</code> and <code>state</code> can be easily hidden by syntactic sugar. For example, <a href="https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration" rel="nofollow noreferrer">a <code>for item in iter</code> loop desugars</a> very similar to <a href="https://github.com/brettcannon/desugar/tree/main#for-" rel="nofollow noreferrer">other languages</a>:</p>
<pre><code>next = iterate(iter)
while next !== nothing
    (item, state) = next
    # body
    next = iterate(iter, state)
end
</code></pre>
<p>Of course, instead of an imperative <code>while</code> loop it could also be desugarred in a functional style using recursion to go along with promoting immutability.</p>

CC BY-SA 4.0
2023-12-21T12:19:17.260Z
2023-12-21T12:19:17.260Z
MisterMiyagi
# Advantages and disadvantages of different iterator protocols
Posted by: username_0 on 2023-05-30
Many high-level languages have some kind of protocol or interface for [iterators](https://en.wikipedia.org/wiki/Iterator), allowing user-defined types to be used in "for-each" loops. A few examples from popular languages:

* In Java, a class which implements the [`Iterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) interface must provide a `hasNext()` method to indicate whether the iteration should continue, and a `next()` method to return the next iterated element. Additionally, there is an optional `remove()` method to remove the element previously returned by `next()` from the underlying collection.
* In Javascript, an object implements the [iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol) by providing a `next()` method returning an object with a `value` property for the iterated element, and a `done` property indicating whether the iterator is exhausted. (When `done` is true, `value` is not required.)
* In Python, a class can be [iterable](https://docs.python.org/3/glossary.html#term-iterable) in two ways:
  + It can have a `__len__` method and a `__getitem__` method to represent an [iterable sequence](https://docs.python.org/3/glossary.html#term-sequence), where each element can be accessed by index;
  + It can have an `__iter__` method returning an [iterator](https://docs.python.org/3/glossary.html#term-iterator) object, which provides a `__next__` method. When this method is called, it either returns the next iterated element, or it raises the special exception `StopIteration` to indicate that the iterator is exhausted.

These protocols differ in the methods that the object must provide, and the expected behaviour of those methods. What are the advantages and disadvantages of these designs, or of other iteration protocols from other languages?
**Tags:** design-choice-comparison iterators
> **Comments:**
> **username_1**: Rust's is similar to Java's except it uses an Option instead of hasNext  
> **username_0**: @Seggan I'd say that makes it more similar to Javascript's ─ it returns a kind of wrapped value which holds both the iterated value and the termination condition. However, Javascript's protocol also allows for `{value: 23, done: true}` to indicate a return value from a generator.  
> **username_2**: Haskell's `Foldable` might be another approach worth noting--not that it actually supports imperative for-loops, but the general idea is certainly applicable: rather than provide hooks for a for-loop to iterate with, the type provides the entire loop construct itself.  
> **username_3**: C#’s `IEnumerator<T>` has `bool MoveNext()` and `T Current`, as well as an optional `void Reset()` to support restarting mid-iteration.  
---
## 6 answers
### Answer by username_4 on 2023-05-30. Score: 8 | Accepted answer
## Java

* a separate `next` and `hasNext` method is inconvenient to implement, but nice for users
  + In many cases it might be actually impossible to implement `hasNext`. Consider the case where you have a iterator representing some data downloaded over the internet. You never know when the other side is going to stop sending.
  + On the other hand, this gives users information that would be impossible to receive otherwise. While a peek adapter can tell you this info it would consume one extra step from the iterator and if that causes side effects it could be undesirable.
  + A hasNext method allows very egronomic looping in a `for(;;)` c-style for loop, if your language lacks a `foreach` equivalent this might be a important feature.
* A `remove` method is quite useful since removing things from iterators while iterating is famously hard, but it's also only useful for some very specific types of iterators so it's weird to have it as part of a interface, even when optional.
* There is no protection from advancing past the end of the iterator

## Javascript

The main downside of Javascript iterators is the limited amount of functions and tooling that supports them, not the interface itself.

The downside of returning both next and done is that it's easy to keep iterating by accident after the end and a type checker won't be able to detect this. If your language has the equivalent of `#[must_use]` to warn about not using a value, that risk could be avoided. JS does not though.

## Python

As pppery said the "old-style" python iterators are quite confusing and often lead to things unintentionally being iterators but then not actually working as iterators.

Raising a exception on error is very verbose to deal with compared to just checking a boolean. On the other hand it's impossible to forget to check which is nice.

## Rust

In rust iterators impelement a trait, `iter.next()` returns a `Option`. This is nice because you are forced to check if you have reached the end and can't cause bugs.

Iterator convenience method are implemented on the trait itself which leads to a nice chaining syntax in reading order, unlike python where you need to nest functions leading to a "in to out" execution order.

Iterables in rust are requied to implement `into_iter()` but in practice most implement `iter()` too which doesn't consume the reference so is usually preferred. Many implement other alternative methods too like `.iter_mut()`. The many ways to convert things into iterators is is confusing.
> **Comments:**
> **username_0** (2023-05-30): This is a good answer, although it focuses mostly on the consumer's side of the protocol (i.e. how to consume an iterable/iterator, if you aren't just using the language's built-in `for` loop that handles things). I suppose that is still important since for some use-cases you do have to consume iterators in user-written code. Nonetheless, I think the implementor's side of the protocol is probably more significant from a usability perspective, since it's more common to have to make a user-defined type iterable.  
> **username_4** (2023-05-30): @kaya3 If you just use the built in iterators in a built in for each loop it doesn't really matter how the protocol is defined since the details will be handled for you  
> **username_0** (2023-05-30): My point is not about built-in iterators, it's about implementing the iteration protocol on a user-defined type, and that being a more common task than having to manually consume an iterator. That said, even when using only built-in iterators for built-in types in a `for` loop, there may be performance considerations between the different protocol designs.  
> **username_3** (2023-05-30): Swift is similar to Rust except that its equivalent to `into_iter` doesn’t invalidate the original object — in practice that usually means it just bumps the refcount, since all the builtin collection types are CoW.  
> **username_4** (2023-05-30): @kaya3 True, there is just not much to say about the difference in implementation for returning a special object or raising a exception. It only really matters for the users of the API. Only Java really has unique features that effect implementors  
> **username_5** (2023-12-21): "A hasNext method allows very egronomic looping in a for(;;) c-style for loop, if your language lacks a foreach equivalent" - It's hard to imagine why a language that requires `for(;;)` style looping would implement an iterator protocol. I think it's literally only C++ that does this, and there it's simpler to use since the equivalent of `hasNext` is basically conversion to boolean (and the equivalent of `next` is an overloaded pointer-dereference operator).  
---
### Answer by username_0 on 2023-05-30. Score: 8
A commonly-cited argument against Python's approach, where the `StopIteration` exception indicates that an iterator is exhausted, is that raising and catching an exception is typically slower than returning a value and checking it with an `if` statement. However, [this is not true in CPython](https://stackoverflow.com/a/20116881/12299000), since the CPython interpreter handles `StopIteration` as a special case in order to make iteration fast. So this is more of an implementation concern than a design concern.

---

Nonetheless, this approach does have a specific pitfall, which is that it allows for non-local control flow effects. This usually only happens by accident, but it's hard to reason about so it can cause bugs which are difficult to diagnose. The issue occurs when `StopIteration` is thrown indirectly by something a `__next__` method calls, rather than intentionally by the `__next__` method itself. In this case, the `StopIteration` exception bubbles up and is caught by whatever consumes the iterator; the consumer then thinks the iterator is exhausted when it isn't necessarily. An example of this occurring "in the wild" is given in [this Stack Overflow Q&A](https://stackoverflow.com/q/71351209/12299000).

The protocol could be changed slightly to prevent this: each iterator could have its own sentinel exception, provided by the consumer, so that the consumer knows it can only be thrown by that specific iterator. However, it would make the protocol more complicated to implement, which doesn't seem worth it to address a pitfall that only occurs very rarely.

The other approaches, which use the return value of the `next` or `hasNext` method to signal termination, don't have this problem because unlike exceptions, return values cannot have non-local control flow effects that automatically bubble up the stack.
---
### Answer by username_6 on 2023-05-30. Score: 5
1. The first Python syntax has the advantage that custom list-like objects become iterable automatically without the user thinking about it.
2. Conversely, the first Python syntax has the disadvantage that it's a heruistic that sometimes isn't correct - if you are implementing a custom dictionary-like object then it will have a `__getitem__` and a `__len__`, but synthesizing them won't produce a useful iterator.
3. Obviously, the Java syntax supports a `remove` method that no other language does, which could be said to be an advantage, as removing elements from the list while iterating it is a common pain point. It also makes it clear that that operation may not be supported if it doesn't make sense.
4. The Java syntax has the disadvantage that it requires the iterator to know whether there is a next element without producing it, which may not be possible for some iterators (think a Python generator - you never know whether it will yield another value or return before running the code). While you can of course work around this by calculating the next value in `hasNext`, that's counterintuitive and confusing.
---
### Answer by username_9 on 2023-12-21. Score: 3
The iteration protocols in the question all rely on mutable iterators: Each iteration has a single iterator object on which a .next method is called for each step; the iterator must mutate its state between .next calls to advance.
An example that also allows immutable iterators is the Julia iterator interface. This is realised by each iteration step providing a state in addition to a value:

iterate(iterable) starts iteration by producing a new state
iterate(iterable, state) resumes iteration from the previous state

By passing the state into each iteration step and receiving the next state, state may be newly created on each step and thus be immutable.
There are some advantages to this:

This protocol is still compatible with mutable iteration as iterate is free to mutate and pass back the state it got or to mutate iterable.
For immutable iterable and state, the tuple of (iterable, state) clearly defines a point in the iteration. This makes it simple and safe to split one iterator into two or more at any point, or to safe an earlier state to roll back to it.
The end-of-iteration can be clearly marked by returning the sentinel value nothing instead of a tuple. This makes it impossible to accidentally proceed with iteration past the end, yet allows the sentinel to still be a valid value as (nothing, state).

The added complexity of lugging around both iterable and state can be easily hidden by syntactic sugar. For example, a for item in iter loop desugars very similar to other languages:
next = iterate(iter)
while next !== nothing
    (item, state) = next
    # body
    next = iterate(iter, state)
end

Of course, instead of an imperative while loop it could also be desugarred in a functional style using recursion to go along with promoting immutability.
---
### Answer by username_7 on 2023-12-20. Score: -1
The language\*1 which has the best possible iterators is, in my opinion, C#. I will explain why.

1. The collection to be iterated does not have to implement any particular interface. All standard collections implement `IEnumerable`, but that is not necessary: if the collection has a `IEnumerator GetEnumerator()` function, it is eligible for participation in a `foreach` loop.
2. If the `IEnumerator` returned by `GetEnumerator()` is disposable, then at the end of the `foreach` loop the disposable will be disposed. Contrast this with Java, where the programmer has to be aware of, and explicitly dispose, any `Iterator` that happens to be `Closeable`.
3. The functions offered by `IEnumerator` are `bool HasNext()`, `void MoveNext()`, and `T Current` (a property.) Thus, if you want access to the `IEnumerator` you can refrain from using a `foreach` loop, and you can use a regular `for` loop instead, where the initialization clause of the `for` loop creates the enumerator, the condition clause invokes `HasNext()`, the step clause invokes `MoveNext()`, and the current value is at any moment available via the `Current` property, which you can invoke multiple times in the same iteration if you need to.
4. This makes it very easy to create ***decorators*** of `IEnumerator`. ([wikipedia](https://en.wikipedia.org/wiki/Decorator_pattern)) Contrast this to Java, where the functions offered by `Iterator` cannot easily be used in a regular `for` loop, and decorators are really hard to write. A filtering iterator cannot be implemented without cumbersome look-ahead logic, and then it is impossible to use it for removing items from the collection because looking ahead means that you are always past the item you want to delete.

---

\*1 I only consider strongly typed languages. Weakly typed languages like Javascript, Python, etc. receive nothing but scorn from me.
> **Comments:**
> **username_4** (2023-12-21): You hate weakly typed languages yet praise duck typing features in C#, ironic  
---
### Answer by username_8 on 2023-12-20. Score: -1
Multiple return
If a language supports returning multiple values in functions or methods, a somewhat better protocol is the generator to return (live: bool, ref data: T?), where live indicates that the enumerator reader should examine the data or keep running, and data is an Optional that indicates if any data is produced in this iteration.
This protocol would cover both direct and async usage, and would further permit filter dropping or accumulating usage in direct code.
Ref return
The ref data instead of simple data is designed to reduce allocation of temporaries drastically in enumerations. To zero, in special.
Other protocols may cause unnecessary allocations by preserving the next data in a backing field, after running/returning of hasMext, and would otherwise impossibilite the creation of generators of "stack only" data types.
The language may offer composite, possible allocating IteratorResult that conforms to Java/C# protocol, that buffers the results outside the generator, instead of forcing the existence of storage by design.
Normal syntax
With or without multiple returns, I also argue that a big step in easing the creation and usage of generators and iterations is to make their syntax simple, instead of special.
A generator is basically an async function that returns multiple times. The same with iterators.
A simple syntax for this wuuld be, for example, and taking note from languages that names the Optional cases with None and Some, to mark generator and/or iterator functions with returning Many
public async Many Filter( Predicate pred )
{ }
---
