# Unexpected behavior of loop over set

I have the following (minimized, but perhaps not minimal) code snippet which is intended to group nodes of graph components. The surprising thing is that it seems to imply that elements of a set are not in the set.

``````ns = [1,2,5,4,3]
cs = Set()
for n in ns
x = nothing
for c in cs
if !(c in cs)
println(c, " is not in ", cs)
end
for m in c
if abs(m-n) <=1

if isnothing(x)
push!(c,n)
x = c
else
union!(x,c)
delete!(cs,c)
end
break
end
end
end
if isnothing(x)
s = Set()
push!(s,n)
push!(cs,s)
end
end
cs
``````

This outputs

``````Set(Any[2, 1]) is not in Set(Any[Set(Any[2, 1])])
Set(Any[2, 1]) is not in Set(Any[Set(Any[5, 4]), Set(Any[2, 1])])
Set(Any[5, 4]) is not in Set(Any[Set(Any[5, 4]), Set(Any[2, 1])])
Set(Any[2, 1]) is not in Set(Any[Set(Any[5, 4, 3]), Set(Any[2, 1])])
``````

Can someone help me understand what is going on here? Is this some scoping or evaluation order issue?

You’re doing two often discouraged things, 1) removing or adding elements to a container while iterating it `delete!(cs,c)`, and 2) mutating the keys of a hash table `push!(c,n)`. The 2nd one is why you’re seeing this apparent paradox; a mutated key’s hash value is not updated, so the hash value computed from its new value will differ and fail to find the entry. A much simpler example:

``````julia> s = Set([[1]]) # [1] entry hashed here
Set{Vector{Int64}} with 1 element:
[1]

julia> s = Set([[1]]);

julia> for c in s  println(c in s)  end
true

julia> for c in s  push!(c, 10)  end

julia> s # [1, 10] entry still has hash from [1]
Set{Vector{Int64}} with 1 element:
[1, 10]

julia> for c in s  println(c in s)  end
false
``````