`Set`s inside `Set`s = dangerous

A colleague discovered the following behaviour. I presume it’s known by those who know, but it doesn’t seem to be documented?

julia> s1 = Set{Int}([1]);

julia> s2 = Set{Int}([1, 2]);

julia> S = Set([s1, s2]);

       # mutate s1 so that it becomes identical to s2:

julia> push!(s1, 2);

julia> S
Set{Set{Int64}} with 2 elements:
  Set([2, 1])
  Set([2, 1])

# S does not realize that s1 and s2 are identical

Python and C++ both error when you try to create a set of sets, for this reason.
Shouldn’t Julia do the same?

2 Likes

This is true of not just Set{T} where T<:Set, but all mutable objects whose hashes change with mutation — and this includes arrays. Even “worse” are dictionaries, where you lose access to any keys that you mutate.

I’m pretty sure this is documented, but perhaps it’s in Dict’s docs. Edit: hrm, yes, these would be good cautions to add to both Set and Dict.

5 Likes

Sets of sets aren’t the issue, it’s mutating anything that’s used as a hash key—dict or set.

2 Likes

IMO the python approach is really annoying. It’s perfectly possible to use a Set{Set} safely (as long as you don’t mutate the inner Sets and having to use a different immutable data-structure just to put something into a collection is something that I would get annoyed by every few months when I was using python more.

3 Likes

It’s useful to have a way to encode “you can’t safely mutate this”, to communicate that fact to other programmers (including myself, later or in other parts of the program). Takafumi was working on a freeze/melt interface I thought was good.

2 Likes

It is, from Julia 1.11: Warn about mutating keys in Dict docstring. by GunnarFarneback · Pull Request #51171 · JuliaLang/julia · GitHub. That PR does not cover Set.

2 Likes