What is a cell in the context of an interpreter or compiler?

closures, compiler-construction, interpreter, python, rust

Solution

In Python, `cell` objects are used to store the free variables of a closure.

Let's say you want a function that always returns a particular fraction of its argument. You can use a closure to achieve this:

def multiplier(n, d):
    """Return a function that multiplies its argument by n/d."""
    def multiply(x):
        """Multiply x by n/d."""
        return x * n / d
    return multiply

And here's how you can use it:

>>> two_thirds = multiplier(2, 3)
>>> two_thirds(7)
4.666666666666667

How does `two_thirds` remember the values of `n` and `d`? They aren't arguments to the `multiply` function that `multiplier` defined, they aren't local variables defined inside `multiply`, they aren't globals, and since `multiplier` has already terminated, its local variables no longer exist, right?

What happens is that when `multiplier` is compiled, the interpreter notices that `multiply` is going to want to use its local variables later, so it keeps a note of them:

>>> multiplier.__code__.co_cellvars
('d', 'n')

Then when `multiplier` is called, the value of those outer local variables is stored in the returned function's `__closure__` attribute, as a tuple of `cell` objects:

>>> two_thirds.__closure__
(<cell at 0x7f7a81282678: int object at 0x88ef60>,
 <cell at 0x7f7a81282738: int object at 0x88ef40>)

... with their names in the `__code__` object as `co_freevars`:

>>> two_thirds.__code__.co_freevars
('d', 'n')

You can get at the contents of the cells using their `cell_contents` attribute:

>>> {v: c.cell_contents for v, c in zip(
        two_thirds.__code__.co_freevars,
        two_thirds.__closure__
)}
{'d': 3, 'n': 2}

You can read more about closures and their implementation in the Python Enhancement Proposal which introduced them: PEP 227 — Statically Nested Scopes.

Problem

Python code objects have an attribute `co_cellvars`. The documentation to PyPy's bytecode interpreter often uses the term Cell. Among other langauges, Rust provides a Cell datatype. Googling suggests they relate to closures somehow. What is a cell, in the context of a programming language implementation? What problem do cells solve?

Original source