Adding Deep Immutability

Agreed but the freeze function is greedy and reaches far from the object that is apparently being frozen. It will easily freeze things that the author does not control unless the object being frozen is very carefully isolated from almost everything in a way that I think many Python programmers will not find easy to understand.

Assuming we can go by the reference implementation I now know the answer to this question:

The answer is yes. The C version of lru_cache cannot be frozen but a Python implementation of it would be frozen and would then be broken. Suppose we have:

def cache(func):

    values = {}

    def cached(*key):
        try:
            return values[key]
        except KeyError:
            val = values[key] = func(*key)
            return val

    return cached

@cache
def square(x):
    return x*x

Then if you make a class that calls this function you can freeze an instance of your class but it will break the square function:

class A:
    def do_stuff(self, val):
        return square(val)

a = A()

print(square(3)) # works

from immutable import freeze
freeze(a)        # seems to work...

print(square(5)) # TypeError: dict is immutable

Now by freezing a you have broken the square function and not just in the sense that it doesn’t work when reached from a. The square function is broken for all callers including those who had no idea that you were going to freeze anything (e.g. the author of the library in which it is defined).

Touching even so much as a single function from a given library might reach the entire library. Unless every single part of that library is freezable (unlikely for any nontrivial library) you can’t even import from the library for risk that any part of it being in the module globals contaminates everything as unfreezable.

What this means is that you have invisible deeply transitive object colouring. The object graph from freezable objects can never reach anything unfreezable. The runtime cannot reliably detect whether things are freezable though (square should not be) and static typing cannot model it either.

6 Likes