Python’s built-in types include frozenset , which is immutable in the same sense as the Guava
collections. It has union and intersection indicated by | and &, which seems a bit
terse to me (there are also methods called union and intersection). Curiously, it
defines the comparison operators (< etc.) as subset/superset tests, which of course
imposes a partial order rather than a total order, so sorting a list of sets by this ordering
doesn’t work. Frozensets are intended for use as set elements or map keys, so some nesting is
supported.
Python’s strings and tuples are also immutable. Clearly attention was paid to preventing the possibility of mutating a set element or map key — good to see.
I see no sign of an immutable map class in the base library (there’s no frozendict).
However, there is a library called Pyrsistent that seems popular and provides functional sets, maps,
bags, and sequences. It has something called “evolvers” which appear to be what Clojure and
FSet call “transients”. They support the standard mutation protocols, so you can pass one to
legacy code that expects a mutable collection and mutates it, and then obtain a persistent copy on
return — a cute feature. Their functional-record class PRecord has some interesting
features, including typed fields and general invariants.
The transform method seems to be a quasi-mutating operator, though I don’t yet understand how
it works.
PVector, their sequence class, has linear-time insertion, deletion, and concatenation; this
could be improved on. The PMap implementation is just a hash table implemented on top of
that; I expect it wouldn’t perform as well as CHAMP (but hey, this is Python anyway). And
PSet is built on top of PMap, rather than being implemented separately.