Tuesday, May 28, 2013

The problem with mutable types

Generally speaking, languages focus mostly on either mutable or immutable types. Of course, it's not quite as clear-cut as that n practice; the usual caveats about broad brushes apply. For instance, Haskell usually describes itself as having immutable types (at least in the intro-ish books), but its MVar is mutable; C and C++ have generally mutable types, but const can give you immutability.

I wasn't sure at first whether I'd want my new language to have mutable types. Even though I want my language to be largely functional (or at least inspired by functional programming), there are times when imperative, mutable-based thinking is more convenient -- or at least more natural to those of us who don't use functional languages every day. More to the point, I found myself wondering: what's really the problem with mutability?

The following Java for loop relies on mutability, but I don't think any programmer could really argue it's hard to follow or especially bug prone:

List<Long> times = new List<>();
for (int i = 0; i < 5; ++i) {
  times.add(System.nanoTime());
}
Put aside the fact that this code isn't very interesting; my point is that it's not very difficult. You can see exactly what it does and what effects it'll have on other code (namely, none). Contrast that to this almost identical example:
List<Long> times = this.getList();
for (int i = 0; i < 5; ++i) {
  times.add(System.nanoTime());
}
It's entirely unclear what this code will do. Will it throw an UnsupportedOperationException from add? Will it succeed, but in doing so break an invariant that another user of the list depends on? Will it modify a list that isn't threadsafe but had been (safely) published to another thread, in the expectation that it wouldn't be modified? Yikes. The problem is not mutability, it's mutable state that exists outside of the current scope. When we created the list in the first method, it was wicked easy to reason about changing it. It's when we got the list from somewhere else that things got complicated. If we had saved the reference to times in the first example to a field in the class, we'd again have to worry that somebody else will change it.

What it amounts to is that mutable state can pull the rug out from under you. I think I have an idea of how to address that without throwing the baby out with the bathwater; stay tuned for a followup post!

No comments:

Post a Comment