Is it defined behavior to modify `iter` while `for`-looping over it?

I don’t think this is necessarily true (depending on how you define difference). For example, if you want to produce collect(1:k) for all k <= n for a given n, you could use

struct S
    n::Int
end

Base.iterate(s::S) = iterate(s, Int[])
function Base.iterate(s::S, state)
    length(state) >= s.n && return nothing
    push!(state, length(state) + 1)
    return state, state
end

Base.length(s::S) = s.n

Then indeed

julia> s = S(3)
S(3)

julia> for i in s
           println(i)
       end
[1]
[1, 2]
[1, 2, 3]

but

julia> collect(s)
3-element Vector{Any}:
 [1, 2, 3]
 [1, 2, 3]
 [1, 2, 3]

as all i point to the same Vector.

Of course, this is a silly example, but I can imagine that in certain situations you might want to mutate the returned item/state in-place for performance reasons. In this case this should definitely be clearly documented. To be fully safe

1 Like