Clojure Gazette 192: Composition is about Decomposing
Composition is about Decomposing
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 wh
y 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!
PurelyFunctional.tv 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 .