Compositionality is an overloaded term; we use it to refer to the ability of various parts to be joined together to create a well-formed composite that is itself reusable.
Different programming models provide varying support for assembling constituent parts into larger wholes. Imperative, procedural code is generally not composable at all; calling a subroutine or method in the course of a procedure is little more than a difference in notation. Object orientation offers some basic facilities for composition, most notably the concept of an attribute where a composite establishes a “has-a” relationship between itself and another entity. Patterns like delegation and pluggable strategies are other ways you can coherently glom smaller pieces together.
Functional programming puts an even greater emphasis on compositionality, making it astonishingly easy to start with small pieces and loosely join them into purpose-built abstractions. We dig into Clojure’s additional specific mechanisms for building abstractions at length in Part II, but the simplest abstraction of all is the function. Because they are generally divorced from data entirely—and, ideally, able to polymorphically work with whatever concrete types of data might be semantically suitable—functions can be used to assemble very powerful composites with a minimum of ceremony.
Function composition has a very distinct meaning in functional programming circles: given any number of functions, it is the ...