Rapha's Rumination Promulgation

October 12, 2009

Concurrency Clojure Stylee

I recently watched Rich Hickey's presentation on Persistent Data Structures and Managed References. I've been impressed with Rich Hickey's ideas on managing state since I first read about it, and this talk didn't disappoint. He begins with what he calls a “little bit of philosophy”. It's essentially an introduction to the ideas he uses in thinking about concurrent programming, and thus those that guided his designs for Clojure. I haven't done much concurrent programming nor really any Clojure, but a lot of these ideas resonated with me and I think that they can inform our understanding of programming in general.

The concepts he defines and uses here are Values, Functions, Time, State, Processes and Identity. I've capitalised these words to signify that I'm referring to Rich's definitions, as I currently understand them. Here's a quick summary:

Values

Values represent data in the problem domain that doesn't change, e.g. 1, π, true, '의', ♣, m, etc. Values may be composites of other Values, e.g. [1,2,3,4] or {red: 0, green: 127, blue: 255}

Functions

Functions are simply an abstraction of expressions on Values, e.g. x => x + 1, or (a, b) => a && b

The expression is constant, though the input Values used may differ. By definition, however, the output is always the same for a given input. These are often called pure functions, or mathematical functions.

Neither Values nor Functions have any notion of Time.

Time

Time is about before/after relationships. It describes the sequencing of events, and thus it is always relative. Time is observable through changes in State, i.e. if asking the same question at a later Time gives you a different answer. The concepts of Time and State are intrinsically linked.

Processes

Processes are programs with State that changes over Time. This gives them observable effects, which is ultimately required in order for them to be useful.

For example, suppose the question were

“What are the files in this directory?”

and the program were

$ mktemp new_file.X

the answer to that question should be different before and after executing the program. mktemp causes an observable change in the State of the filesystem.

Identities

But how do we manage this State safely, particularly in the presence of concurrency?

Clojure's answer is:

State is a Value of an Identity at a Time.

An Identity is a single conceptual entity that takes a sequence of Values over Time. There is a causal continuity between these Values - each one being some Function of the previous. But in changing the Identity's Value, we don't forget that the Identity had a different Value before, nor do we assume that the current Value is the Value it always had. There is an explicit understanding that an Identity's Value is only meaningful in the context of a particular Time.

Rich Hickey summarises this point with: “Things don't change in place”, because “place includes time”.

Finally

Rich goes on to talk about how these ideas are implemented and employed in Clojure, which is interesting. I'd definitely recommend watching the whole talk, even two or three times if necessary :-)