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