Clojure Gazette 192: Composition is about Decomposing

Sign up for weekly Clojure tips, software design, and a Clojure coding challenge.

Composition is about Decomposing
Clojure Gazette
Issue 192 - September 26, 2016
Hello, functional readers! When I first started using Clojure, I was struck by how composable things felt. Arguments seemed to line up just the way I needed them. Data output from one function was just the shape another function wanted. How was Clojure doing this? Further, so often I would need a certain function to transform data. Instead of writing the function myself, I'd check first in the core library. More often than not, the function was there already, like Rich Hickey had already been down the same road. I've been pondering this experience ever since I started with Clojure back in 2008. How were things so composable in Clojure? And how was it so complete for such a new language? Some people would point to the single designer of the language as the cause. One person in control can give a cohesion that a committee usually can't. But many languages are designed by one person. Python, for instance, is a very cohesive language as far as its philosophy goes. But it does not have the composability of Clojure, in my experience. No, the single designer helps, but it's not a sufficient condition. The philosophy the designer enforces plays a big role. Could it be that the parts were specifically designed to compose? By that, I mean that Rich Hickey thought really hard about lots and lots of combinations of the core library functions. And by trying out so many different combinations, he could see a way that worked really well, and that's what ended up in Clojure. But the number of combinations needed to cover even a small fraction of the space is too big for any mind, including Rich Hickey's. By analogy, Legos aren't made composable by trying out every combination. There's a better, more systematic way. And in the words of Rich Hickey himself: Good design is not about making grand plans, but about taking things apart.When we take things apart, we get more things. But each thing is by definition simpler than the thing it was part of. And those smaller things reveal an underlying structure. It is that underlying structure where composability begins. We see it in chemistry. The periodic table describes an underlying structure, letting us compose elements in ways unthinkable before. It happens in architecture: by separating tension elements from compression elements, we can recombine them in better ways to create better buildings. The structure we reveal becomes a unifying field. The reason Legos are composable? Because all of the pieces are built on the same structure: a rectilinear grid with a top (a stud), a bottom (the tubes), and sides (flat). Of course, there are exceptions, but the exceptions make composition harder. Clojure has done this. Collections are broken down into their component interfaces. You use these interfaces orthogonally to how the collections are implemented. One interface called Associative deals with key-value associations. There are three cohesive methods on that interface, which were probably discovered to be so cohesive by trying to pull them apart but not finding any beneficial way to do so. That interface forms a part of the underlying structure of the language that many functions are built on. It's a cohesive structure and it's deeper than most languages are built on. That structure's existence means you will often find the perfect function in the core library for your need. Of course you'll need this: the structure is so unifying that its implications become self-evident. Just like with the periodic table, chemists could predict the discovery of new elements, so too can the combinations of parts of the structure be defined before they are needed. When we pull things apart, we are looking for that structure. We're looking for a level where things unify as if by nature. We often don't have the time or motivation to dig so deep, which is why the experience of such great design is rare. But when we experience it, it is magical. I wonder if such a decomposition of things is always possible? Is there some sign that we are deep enough into the structure for our needs? I would guess that is is always possible and that you can't know until you dig what you'll find. But in the long run, there's always increasing benefits the lower down you go. Rock on! Eric Normand <> is the best place to learn functional programming. At least that's what I'm trying to make it. And I need your help! I need other teachers who want to share the great ideas of the past 50 years of programming and get paid to do it. If you're interested, please watch the invitation video.