25 Jan 2017

Following a brainwave, a scientist writes something important on a blackboard. Then in large, friendly letters he writes above it, “PLEASE DO NOT ERASE THIS!”
He leaves the room to grab a coffee.
Five minutes later he returns, and another scientist is cheerfully cleaning the blackboard, removing all trace of that world-changing idea.
“B-b-but - didn’t you see the note???” yelps the first.
“The one that said, ‘don’t rub this out?’” replies the second.
“Yes!”
“Oh…I thought it meant don’t get rid of the blackboard. I didn’t realise the contents were important too.”

So it may be with immutability. Take Scala for instance. Put an object into a scala.collection.immutable.List and the list is guaranteed never to change. It will always be a one-element list with that object in it. But the object itself? No special guarantees there - it’s still mutable as it was before.

In this case, the list is the wall and the object is the blackboard - one is firmly nailed to the other. But just like the blackboard, the object can change its meaning at will.

Similarly, in recent JavaScript specs we have Object.freeze() which many will say makes a JavaScript object immutable. And technically it does - the object’s keys will not change, and the pointers1 associated with those keys will not change, but the things they point to might. JavaScript’s Object.freeze() only freezes top-level properties. In which case it might be better named Object.frosting(). Again, the blackboard is fixed, but what’s written on it is a movable feast.

All this seems odd coming from languages that have immutability as a core concept, like Clojure & Haskell. In those languages, if I give you access to my immutable list, you can do anything you like with it and it won’t affect me. I don’t need to know what you did; I don’t need to trust you to behave yourself; I can rely on guarantees from the language itself. If you try to write on my blackboard, you’ll find yourself transported to another room, with an identical blackboard that you’re free to do whatever you like with. Mine remains untouched.

And so sadly it seems that, like “isomorphic”2, “immutable” now has two meanings depending on where you first heard about it. In the new meaning, you need to know some implementation details before you can say what part of the data is fixed, and what is subject to change. That doesn’t sound very immutable to me…

(I confess I struggle to see the value of immutable frosting. It seems like, “immutability made easy for the language implementor,” not, “made valuable for the programmer.”)

Still, for the record, here’s a definition of immutability that I think’s unambiguous and useful:

If you call a pure function with the same immutable argument, you always get the same result.3

Sounds obvious, but up until a few days ago I thought that was the only meaningful meaning ‘immutable’ could have…

Footnotes

  1. I’m still bothered by JavaScript being a language where there are no C-style pointers, but pointer-based semantics are everywhere

  2. Meaning, “you can convert a value from one type to another and back without losing information,” or, “the same HTML can be rendered on the backend or the frontend.” 

  3. You really can cross the same river twice. 

comments powered by Disqus