10.4.7 Python

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.