On Immutability

Programming languages are super fun. Like people, they too belong in family trees and follow an evolutionary graph. They liberally copy, adapt and improve upon ideas from each other all the time. You know an idea/style is a good one, if you see it being retained, borrowed or made the default in newer generation languages.


This essay looks at a simple idea called Immutability and explores how far we can stretch it.


Immutability is a constraint. It's an implementation style. Take for instance strings. You may implement C/C++ strings as mutable. Java implements strings as immutable. The immutable style subtly shifts the emphasis from a variable's physical memory location to it's value.


//Java
String sample = "hello";
String ref = sample;

System.out.println(sample.hashCode());
// prints something

sample = sample + "!";
System.out.println(sample.hashCode());
// prints something else
//sample is now "hello!", ref remains as "hello"


The benefits of the Immutable style was not very apparent back in the day. This idea was hard won. In C/C++ a string is no different from an array of integers. Its just terminated with a 0 at the end. You can change characters in place if you know what you are doing.


//C++
char* sample = "hello?";
char* ref = sample;

sample[5] = '!';
//both sample and ref are now "hello!"


Over time, it has become obvious that many nasty errors just disappear when strings are not manipulated in-place like in the above C++ example. This is especially desired in big projects with many modules, contributors and libraries. And in concurrent applications, Immutable design is a blessing! A buggy library bringing down the entire application because it changed memory that some other part or thread was referencing was, and still is, a way too common error. Such errors are elusive to hunt down, cumbersome to reproduce and painful to resolve.


Hence modern languages have made strings immutable by default and encourage an immutable style of programming as a best practice. If a string identity (the mutable variable "sample" is the identity in the Java example above) needs to change during a program's execution, you don't change it in-place, you just assign a new copy (the literal "hello!" post assignment is the identity's new value) to it. The concept of values, literals and the representation of these literals are closely related. Every possible value can be represented by a literal and both the value and its literal are syntactically equivalent.


If immutability is a thesis then the separation of identitity and values is its corollary. If 90% of your code deals with values, and you program primarily by manipulating these values in small functions that have 0 side effects, you have functional programming. Almost.


If strings can be values, what else can be made a value? Can collections like vectors, lists and hash-maps be made a value? - yes - Clojure has made this style the default and expanded on it and made it pervasive. In Clojure, even collections are values. i.e A huge vector or a hash map behaves like an immutable string. If you append an element to a vector, you get a new copy. Internally, Clojure has managed to pull this off by implementing its basic types as persistent data structures. Take some time to reflect and internalize this statement. Even collections are values. A collection like a hash map or a vector can contain other collections as its elements. Even such nested collections are values. No matter how large. No matter how deeply nested. Everything is a value. Everything is immutable.


If collections can be values, what else could be made a value? Can a code base be made a value? - yes - git, the repository hosting your code. Think of this git repo as the identity. Each commit - annotated by a unique SHA-1 and representing an entire blob of file changes representing the commit can be thought of as a value ingested into the identity. And by doing so the repo is "patched" to its new state on every commit. Do you find such code bases with a well-known catalogue of patches useful? Has it changed your features building style, reasoning, reviews and collaboration around code?


What else can benefit from this style of modelling? Can an entire database be modelled as a sequence of values? - yes - Cognitect, the company that has brought us Clojure, has designed a database that behaves similar to git. It's called Datomic. The properties of this database radically changes the way you think about, model, mock, investigate data issues and migrate databases. Datomic is not the only database doing this. Even Blockchains adopt this exact same semantics. "Reality" is just derivable. By iterating through all the commits or blocks that make the consensus time line in order, you construct reality. This kind of modelling removes all ambiguity to state yielding unprecedented data consistency and auditability. And, um, you also have a functioning time machine as a side effect.


What else can be benefit from this style of modelling? Can an entire app/ game be modelled as a sequence of values? - yes - Among many others, Reagent - a Clojurescript library wrapping Facebook's React takes this approach. In this approach your whole app is modelled as a value represented by a hash-map like thing called 'ratom'. The ratom takes centre stage and all the app's interactions involve changing the ratom through controlled operations. This is a very elegant, "functional" approach brought to developing and experiencing UIs. I believe UIs should be developed in no other way.


If apps and games can be modelled as values, what else can be similarly modelled? Can our entire world be modelled as sequence of values? - yes - The idea that we are deeply buried in some interaction nested inside a sequence of gargantuan immutable literals being emitted at some 60 frames a second is extremely attractive to the programmer in me. As interest explodes in VR, AR and MR apps, this style of modelling will likely be upvoted over other models by future stake holders.


In short, we all will become time travellers and Immutability is here to stay...