5 ms·
I wonder whether Raymond Hettinger has an opinion on this PEP. A long time ago, he wrote: "freezing dicts is a can of worms and not especially useful". https:/
by pansa2 10mo ago
I wonder whether Raymond Hettinger has an opinion on this PEP. A long time ago, he wrote: "freezing dicts is a can of worms and not especially useful".
https://mail.python.org/pipermail/python-dev/2006-February/060793.html https://mail.python.org/pipermail/python-dev/2006-February/0...
- mvanbaak 10mo agoThis was 19 (almost) 20 years ago. As stated in the lwn.net article, a lot of concurrency has been added to python, and it might now be time for something like a frozendict. Things that were not useful in 2006 might be totally useful in 2026 ;P Still, like you, I'm curious wether he has anything to say about it.
- aewens 10mo agoI think Raymond Hettinger is called out specially here because he did a well known talk called [Modern Dictionaries](https://youtu.be/p33CVV29OG8 https://youtu.be/p33CVV29OG8) where around 32:00 to 35:00 in he makes the quip about how younger developers think they need new data structures to handle new problems, but eventually just end up recreating / rediscovering solutions from the 1960s. “What has been is what will be, and what has been done is what will be done; there is nothing new under the sun.”
- sesm 10mo agoSince that time HAMT was invented and successfully used in Scala and Clojure, so this talk didn't age well.
- Someone 10mo agoWikipedia (https://en.wikipedia.org/wiki/Hash_array_mapped_trie https://en.wikipedia.org/wiki/Hash_array_mapped_trie) links to the paper describing HAMT (https://infoscience.epfl.ch/server/api/core/bitstreams/f66a3023-2cd0-4b26-af6e-91a9a6ae7450/content https://infoscience.epfl.ch/server/api/core/bitstreams/f66a3...) and claims that is from 2000. That talk is from 2016.
- ndr 10mo agoHAMT weren't immutable/persistent until Clojure though: https://en.wikipedia.org/wiki/Persistent_data_structure#Persistent_hash_array_mapped_trie https://en.wikipedia.org/wiki/Persistent_data_structure#Pers... Still well before the talk.
- zelphirkalt 10mo agoDo you know of any implementation, that is well annotated/commented, so that it is easy to understand?
- kzrdude 10mo agoI think he was always reluctant to add features, and his version of Python would be slimmer, beautiful, and maybe 'finished'. His voice is definitely not guiding the contemporary Python development, which is more expansionist in terms of features.
- jonathaneunice 10mo agoThat's a great link and recommended reading. It explains a lot about the design of Python container classes, and the boundaries of polymorphism / duck typing with them, and mutation between them. I don't always agree with the choices made in Python's container APIs...but I always want to understand them as well as possible. Also worth noting that understanding changes over time. Remember when GvR and the rest of the core developers argued adamantly against ordered dictionaries? Haha! Good times! Thank goodness their first wave of understanding wasn't their last. Concurrency and parallelism in Python was a TINY issue in 2006, but at the forefront of Python evolution these days. And immutability has come a long way as a design theme, even for languages that fully embrace stateful change.
- zahlman 10mo ago> Also worth noting that understanding changes over time. Remember when GvR and the rest of the core developers argued adamantly against ordered dictionaries? Haha! Good times! The new implementation has saved space, but there are opportunities to save more space (specifically after deleting keys) that they've now denied themselves by offering the ordering guarantee.
- jonathaneunice 10mo agoOrdering, like stability in sorting, is an incredibly useful property. If it costs a little, then so be it. This is optimizing for the common case, where memory is generally plentiful and dicts grow more than they shrink. Python has so many memory inefficiencies that occasional tombstones in the dict internal structure is unlikely to be a major effect. If you're really concerned, do `d = dict(d)` after aggressive deletion.
- zahlman 10mo ago> Ordering, like stability in sorting, is an incredibly useful property. I can't say I've noticed any good reasons to rely on it. Didn't reach for `OrderedDict` often back in the day either. I've had more use for actual sorting than for preserving the insertion order.
- zahlman 10mo ago> Another PEP 351 world view is that tuples can serve as frozenlists; however, that view represents a Liskov violation (tuples don't support the same methods). This idea resurfaces and has be shot down again every few months. ... Well, yes; it doesn't support the methods for mutation. Thinking of ImmutableFoo as a subclass of Foo is never going to work. And, indeed, `set` and `frozenset` don't have an inheritance relationship. I normally find Hettinger very insightful so this one is disappointing. But nobody's perfect, and we change over time (and so do the underlying conditions). I've felt like frozendict was missing for a long time, though. And really I think the language would have been better with a more formal concept of immutability (e.g. linking it more explicitly to hashability; having explicit recognition of "cache" attributes, ...), even if it didn't go the immutable-by-default route.
- pansa2 10mo ago> ImmutableFoo as a subclass of Foo is never going to work. And, indeed, `set` and `frozenset` don't have an inheritance relationship. Theoretically, could `set` be a subclass of `frozenset` (and `dict` of `frozendict`)? Do other languages take that approach? > linking [immutability] more explicitly to hashability AFAIK immutability and hashability are equivalent for the language's "core" types. Would it be possible to enforce that equivalence for user-defined types, given that mutability and the implementation of `__hash__` are entirely controlled by the programmer?
- chriswarbo 10mo ago> Theoretically, could `set` be a subclass of `frozenset` (and `dict` of `frozendict`)? At one extreme: sure, anything can be made a subclass of anything else, if we wanted to. At the other extreme: no, since Liskov substitution is an impossibly-high bar to reach; especially in a language that's as dynamic/loose as Python. For example, consider an expression like '"pop" in dir(mySet)'
- tremon 10mo ago> consider an expression like '"pop" in dir(mySet)' class frozenset: pass class set(frozenset): def pop(self, key): pass I don't see why hasattr(mySet, 'pop') should be a problem here?
- dkarl 10mo agoIt's interesting that he concludes that freezing dicts is "not especially useful" after addressing only a single motivation: the use of a dictionary as a key. He doesn't address the reason that most of us in 2025 immediately think of, which is that it's easier to reason about code if you know that certain values can't change after they're created. What a change in culture over the last 20 years!
- morshu9001 10mo agoYou can't really tell though. Maybe the dict is frozen but the values inside aren't. C++ tried to handle this with constness, but that has its own caveats that make some people argue against using it.
- krick 10mo agoIndeed. So I don't really understand what this proposal tries to achieve. It even explicitly says that dict → frozendict will be O(n) shallow-copy, and the contention is only about O(n) part. So… yeah, I'm sure they are useful for some cases, but as Raymond has said — it doesn't seem to be especially useful, and I don't understand what people ITT are getting excited about.
- deleted 10mo ago[deleted]
- morshu9001 10mo agoMaybe treating Python like a systems language, so applying the same reasoning for const in C++ and Rust to it
- ndr 10mo agoImmutability it's a joy to work with. Ask anyone who's worked with Clojure's dicts.
- morshu9001 10mo agoI agree, same with frozenset. If you really want to use one of those as a key, convert to a tuple. There might be niche use cases for all this, but it's not something that the language or even the standard lib need to support.
- boothby 10mo agoProblem being that sets aren't consistently ordered and conversion to a tuple can result in an exponential (specifically, factorial) explosion in the number of possible keys associated with a single set. Nor can you sort all objects. Safe conversion of sets to tuples for use as keys is possible but the only technique I know requires an auxiliary store of objects (mapping objects to the order in which they were first observed), which doesn't parallelize well.
- morshu9001 10mo agotuple(sorted(s)) and if you can't even sort the values, they're probably not hashable. I get that this involves a copy, but so does frozenset, and you can cross that bridge in various ways if it's ever a problem.
- boothby 10mo agoHere are some types that support hashing: str bytes int, float complex tuple frozenset Aside from int and float, you cannot perform comparisons between objects of different types. Moreover, you cannot sort complex numbers at all. I have crossed that bridge, and I'm telling you (again) that a sorted tuple is not a generic solution.
- morshu9001 10mo agoI'm not saying the problem with tuple doesn't exist, but that there doesn't need to be a built-in way to deal with it. If for some unfortunate reason you've got a mixed-type set that you also want to use as a dict key, you can write a helper.
- pkulak 10mo agoThis is why I love how Rust approached this; almost by accident to make borrow checking work. Every reference is either mutable or not, and (with safe code), you can't use an immutable reference to get a mutable reference anywhere down the chain. So you can slowly construct a map through a mutable reference, but then return it out of a function as immutable, and that's the end of it. It's no longer ever mutable, and no key or value is either. There's no need to make a whole new object called FrozenHashMap, and then FrozenList, and FrozenSet, etc. You don't need a StringBuilder because String is mutable, unless you don't want it to be. It's all just part of the language. Kotlin _kinda_ does this as well, but if you have a reference to an immutable map in Kotlin, you are still free to mutate the values (and even keys!) as much as you like.
- the__alchemist 10mo agoMy favorite part of rust is its explicit control over mutability, in the manner you describe.
- rcxdude 10mo agoOnly if you're returning a reference or wrapping it in something that will only ever return a reference. If you return an object by value ('owned'), then you can do what you like with it and 'mut' is just an light guardrail on that particular name for it.
- vlovich123 10mo agoYou cannot return an immutable version. You can return it owned (in which case you can assign/reassign it to a mut variable at any point) or you can take a mut reference and return an immutable reference - but whoever is the owner can almost always access it mutably.
- pkulak 10mo agoArg, you’re right. Not sure what I was thinking there. I still think my point stands, because you get the benefits of immutability, but yeah, I didn’t explain it well.
- 10mo ago
- eru 10mo agoHa, Raymond Hettinger has a lot of opinions. Great guy and I admire his dedication to Python, but in my own experience (and the experience of some other contributors), he has a chilling effect on contributions to certain parts of the CPython code base. Not that it's entirely unwarranted, of course.