Names, Values, Identities, States and Time

“No man can cross the same river twice, because neither the man nor the river are the same.”

Heraclitus

The following post is extracted & paraphrased from Rich Hickey's excellent Are We There Yet? - specifically the section of the talk that focuses on the model for discussing and thinking about the titular concepts. These concepts are in turn taken from the philosophical writings of Alfred North Whitehead (a co-author of Principia Mathematica).

I often find myself wanting to explain this core concept to people who are new to Clojure, and particularly people who I am trying to make into people who are new to Clojure. While I think I have a good handle on this concept in my head - I sometimes struggle to explain it succinctly, hopefully this post achieves that goal.

Definitions

These definitions are not really globally applicable, but they represent the precise meaning I try to capture when discussing values changing over time in the context of software development and programming.

Value

A value is some measurable quantity, magnitude or amount for which its equivalence to some other value can be determined. A value can also be some immutable composite of other values. The number 42 is a value, the string "Hello World" is a value, the list (1, 2, 3) is also a value.

Identity

An identity is some composite psychological concept we apply to a succession of values over time where they are in some way causally related. You are an identity, I am an identity, a river is an identity (see below).

Name

A name is simply a label that we apply to an identity or a value to make it easier to refer to. The same identity can have many names. "Glen", "Glen Mailer", "Mr Mailer", "Glenjamin" and "@glenathan" are all names which could legitimately be considered to refer to the identity that is myself in the appropriate context. Likewise the "Answer to the Ultimate Question of Life, The Universe, and Everything" is a name for the value 42.

State

A state is simply the value of an identity at a particular time. A snapshot, if you will. Under this definition state does not change, and thus there is no such thing as "mutable state".

Time

Purely relative, it has no dimensions - it can only tell us whether something happened before or after some other thing (or at the same time).

The River

Let us consider the title quote in the context of these definitions. To help us examine the proverbial river under this light, we shall give ourselves the same powers as when running a computer program but in the real world - which requires us to sidestep some fairly fundamental physics - hopefully this will not cause any lasting damage.

The third-longest river in Asia runs through China. Depending on context it is known as the "Yellow River", "Huang He", "རྨ་ཆུ།", "the cradle of Chinese civilization" and "China's Sorrow". All of these are names for the same river, which itself is an identity.

If we were to freeze an instant in time into a snapshot of our proverbial river crossing, this state would contain a value composed of a large number of atomic (in the irreducible sense) smaller values. For simplicity, lets assume that water molecules are immutable. In this case then the state of the river we are crossing can be said to be the current arrangement of all these immutable water molecule values.

At some point in the future when returning for our second crossing, we take another snapshot of the river as our new state. The river's value is again the arrangement of all the immutable water molecules - but this time they are all different molecules with different values.

The state of the identity which is the river named "Huang He" at this later point in time is measurably different from the value we took during the first crossing.

In Clojure

Since immutability is at it's core, we'll start here for some code examples.

The following code should work correctly when pasted into a running Clojure REPL.

In JavaScript

JavaScript doesn't have the same set of immutable primitives, but we can achieve a similar effect with a little sleight of hand.

The following code should work correctly when pasted into the browser console or a Node.js REPL line-by-line.

Summary

The ancient Greeks knew about the perils of mutable state a long time ago - we're only now rediscovering this for ourselves.

In a language like Clojure, that was designed from the ground up with this in mind, it's easy to take back control and tease apart the separate concepts I've described. Even in a language like JavaScript, designed in a week at a time when mutability was commonplace, we can achieve a similar effect with a measure of self-control. There are also libraries like mori and immutable-js which provide much fuller implementations of the data-types required to avoid mutability.

If you remain unconvinced, I recommend watching Are We There Yet?. If you're still not sure after that, you're either a far better programmer than me, or you're yet to experience the pain of trying to reason about a large codebase riddled with unchecked mutability.

Addendum

As well as the above definitions, Are We There Yet? contains this gem, which is Rich visualising the idea of obvious complexity while saying "Grrrrr".









5 responses
Note that time is not merely the ability to construct a total ordering between instants, but also, at least some of the time, a notion of measure between them. You use this yourself when you thread delay for 1000ms. The distinction between time that is discrete, continuous, or merely a construct of interleaving things until they have a definite total order sits at the center of the various reactive paradigms.
This is very well-explained. I would add a couple small points. Names do not refer only to entities. The identifier created by a let binding, for instance, is a kind of name for a value, rather than a name for an identity that is described by some value. Second (and this is something I've only been learning about recently), you can find other terminology for some of these concepts in other technical communities. For instance, the identity / value distinction in Clojure seems to echo the entity / value object distinction in the domain-driven design literature. And there's an even deeper investigation of a lot of these ideas in the analytical philosophy literature, which has developed very exact definitions of identity (sameness), equality, naming, and reference.
Thanks for the feedback Alexis! I've updated the post to incorporate that names can also refer to values - good point. On the DDD side of things, my understanding is fairly light - but I believe there is still a slight difference. Although the entity/value distinction is drawn, I think entities still complect the concepts of identity and value. As best I can tell, a DDD entity is not simply thought of as a composite of values over time. I didn't emphasise it much in the post, but as I understand it the terms discussed and the Rich Hickey talk are directly inspired from philosophy literature. In an earlier draft I had a section about other media that refers to these concepts - including the Pratchett book "Thief of Time", but I removed this section as it was poorly structured. If you have any links where I could read more about the philosophy side of this I'd be very interested and happy to append to the post.
I think Rich has quoted Whitehead and Heraclitus a couple times for the sake of illustration, but I think he's also said that philosophy was not a direct influence on his thinking. I have not seen anyone discuss the connections between analytical philosophy and concepts used in data modelling and software architecture, but the connections are definitely there. I think that's an actually quite plausible source for well-refined, "turnkey" ideas. But I don't think anyone has gone there yet. I'm thinking about it, anyway! As regards DDD, I've started to read the books but I don't know it well. But according to what I've read so far, the Clojure identity/value distinction seems extremely similar to the DDD entity/value object distinction. Here is a quote from Eric Evans, explaining entity/value objects on the Software Engineering Radio podcast in 2006, years before Clojure was introduced: [begin quote] "But to distinguish between these two ..., the entity revolves around identity and continuity, and not around the properties of the thing. So in a metaphor, if you think of a living person, there's almost no attribute of that person that exists throughout the lifespan of that person. And of course the entity that we associate with that person exists in fact long after they are dead and their body is gone. So there's no actual property that this person has. But there is an identity. And it ties together things that we think are important. So the same is true of objects.... You may have a customer object and your customer object may have importance in the sales-related part of your software. You may track information about sales calls and historical sales volumes and so on.... In another part of your software you may be actually handling the service to this customer. You may need completely different information about that customer... And yet it's the same entity. Contrast this to a value object. In a value object, if it's well-formed, you don't care about identity. There's no meaningful identity at all. A good example of a value object, kind of a canonical example of a value object, is color. If you want to describe the color of something, you say it's red, you say it's green. You don't care if the red color you were referring to yesterday is the same particular red that it is today. I mean, you care that it is the same color. but that is a value that you can describe. You don't care if it's the same red object. Even in terms of how you would handle implementation, do you care about history. when you change this object do you throw it away and get another one? The more that kind of thing you can do, having immutable objects that just are what they are, and when you no longer want them you just throw them away and get another one. Your system will be a lot easier to manage. Because you can make statements about these objects that are firm and always true statements, which you can't do about an entity in the same way. Entities are a lot harder to manage, and a lot of the meaning of a model comes from those value objects." [end quote] To me, this seems to have all the essential conceptual ingredients of the Clojure model, just under slightly different names. Here are similiarities I notice: 1. an "entity" as a name for a kind of thing in the world, specifically, the kind of thing that possess continuous identity through time (in comparison, the Clojure model says that such things *are* "identities", rather than talking about them _having_ identity, which is conventional usage) 2. the observation that an entity does not have stable properties, and is just a perceptual abstraction that "ties together things we think are important". This parallels Rich's observation that an identity is to some degree a perspective we impose on the flux of values 3. the ontological observation that _qualities_ of thing do not have identity, and are values, so that it only makes sense to talk about them being equal or not 4. the related pragmatic observation that it makes sense to model qualities with immutable value objects, because "you can make statements about these objects that are firm and always true" and "your system will be a lot easier to manage". And in the DDD world, I notice that the objects representing entities are sometimes referred to as "reference types". Just like in the clojure world, the objects that represent identities are reference types (atoms, agents, vars). In addition, the DDD literature has an idea of "aggregates" and "aggregate roots", which I think corresponds to the Clojure dictate to define one reference type that contains a value, which may be a compound value but it immutable all the way down. So to me it seems that, just as an intellectual model for thinking about how to use software to model change in the world, the Clojure model *very strongly* echoes these ideas that were already present in DDD. But of course Clojure brings them together in a tidy way, with a language that really encourages you to use this model consistently. Clojure also provides, of course, concurrency primitives, persistent data structures, and other technologies that make it easier to program with this model in mind. BTW, I have not seen this noted anywhere in the Clojure community. I just noticed all of this myself in the last few days.
Another great comment, I think you should probably turn that into a blog post in its own right :) What you're saying certainly sounds more like the Clojure definitions than I had realised. I still get the sense that the Entity's direct properties are considered mutable references to particular values, rather than taking it that one step further and treating the entity at a particular point in time as a value.