Iterators.Stateful
has the definition
mutable struct Stateful{T, VS, N<:Integer}
itr::T
# A bit awkward right now, but adapted to the new iteration protocol
nextvalstate::Union{VS, Nothing}
# Number of remaining elements, if itr is HasLength or HasShape.
# if not, store -1 - number_of_consumed_elements.
# This allows us to defer calculating length until asked for.
# See PR #45924
remaining::N
@inline function Stateful{<:Any, Any}(itr::T) where {T}
itl = iterlength(itr)
new{T, Any, typeof(itl)}(itr, iterate(itr), itl)
end
@inline function Stateful(itr::T) where {T}
VS = approx_iter_type(T)
itl = iterlength(itr)
return new{T, VS, typeof(itl)}(itr, iterate(itr)::VS, itl)
end
end
In the constructor, it calls
function iterlength(it)::Signed
if IteratorSize(it) isa Union{HasShape, HasLength}
return length(it)
else
-1
end
end
but what’s the point of this Signed
restriction? Subtypes of Integer
that aren’t subtypes of Signed
are ruled out as the length. For example, this doesn’t work:
julia> using Infinities
julia> x = 1:∞
1:∞
julia> Iterators.Stateful(axes(x,1))
ERROR: MethodError: no method matching Signed(::InfiniteCardinal{0})
Closest candidates are:
(::Type{T})(::T) where T<:Number
@ Core boot.jl:792
(::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number}
@ Base char.jl:50
(::Type{T})(::Base.TwicePrecision) where T<:Number
@ Base twiceprecision.jl:266
...
Stacktrace:
[1] convert(#unused#::Type{Signed}, x::InfiniteCardinal{0})
@ Base ./number.jl:7
[2] iterlength(it::InfiniteArrays.OneToInf{Int64})
@ Base.Iterators ./iterators.jl:1413
[3] Base.Iterators.Stateful(itr::InfiniteArrays.OneToInf{Int64})
@ Base.Iterators ./iterators.jl:1406
[4] top-level scope
@ REPL[47]:1
The fact that this is infinite is a red herring, as this would rule out static integers and such as well.