# Does length(itr) need to be invariant? (stateful iterator)

**URL:** https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170
**Category:** General Usage
**Tags:** question, iterators
**Created:** [August 14, 2024, 9:31am UTC](https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170 "2024-08-14T09:31:57Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 14, 2024, 9:31am UTC](https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170/1 "2024-08-14T09:31:57Z")

</div>

I have a calculation that tracks a large state for a cohort of economic agents that have a finite lifetime. A certain summary statistic is implemented with the iteration protocol.

If you imagine `c` below to be something large, black boxy, and mutable, the following MWE should convey the idea:

```julia
mutable struct ExampleItr
    c::Int
end

function Base.iterate(itr::ExampleItr, _::Nothing = nothing)
    iszero(itr.c) && return nothing
    c = itr.c
    itr.c -= 1
    c, nothing
end

Base.length(itr::ExampleItr) = itr.c

Base.eltype(::Type{ExampleItr}) = Int

```

The use case is the following: the functions that use the iterator may copy the whole thing at a certain point, and restart from there with different parameters (not included above). Eg

**What I find problematic is that `length` depends in the state.** It is fine it it is understood that the users of the interface may call `length` at the very beginning, and not after. It is not if it can be called throughout the iteration and is expected to return the same value.

The iterator protocol does not say when `length` may be called, so in theory it could be called anytime.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 14, 2024, 9:34am UTC](https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170/2 "2024-08-14T09:34:05Z")

</div>

The alternative is

```julia
Base.IteratorSize(::Type{ExampleItr}) = Base.SizeUnknown()

```

which is always correct, it just precludes certain optimizations.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [August 14, 2024, 12:00pm UTC](https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170/3 "2024-08-14T12:00:09Z")

</div>

Set `SizeUnknown()` and leave `length` undefined:

> <https://github.com/JuliaLang/julia/pull/51747>
>
> Stateful iterators do not have a consistent notion of length, as it is continuou…sly changing as elements are removed. As the main purpose of Stateful is to take elements from multiple places, any notion of HaveShape is invalid for those cases, and thus not useful in general.
> 
> Fix #47790
> ~Blocked on #51869~

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 15, 2024, 10:45am UTC](https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170/4 "2024-08-15T10:45:36Z")

</div>

This makes a lot of sense, I am wondering it this point should be mentioned in the manual (very briefly). I can make a trivial PR.

Very little is documented about stateful iterators. The specific implementation `Iterators.Stateful` is one of the most mysterious parts of Julia for me. I am not sure it gets a lot of usage.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [September 24, 2024, 8:49pm UTC](https://discourse.julialang.org/t/does-length-itr-need-to-be-invariant-stateful-iterator/118170/5 "2024-09-24T20:49:54Z")

</div>

The change is now in the release notes for v1.11:

> <https://github.com/JuliaLang/julia/pull/55858>
>
> Will update History.md on master if this gets merged.
> 
> xref #47790
> 
> xref #51…747
> 
> xref #54953
