The Expression Problem is faced by all programmers who create anything other than simple programs. Represent abstractions with types, add procedures, methods or functions (choose your term) to manipulate those types, and some time later, one is invariably faced with the 2 problems: - adding new types/ classes - adding new operations/ functions This be the essence of the problem of programming abstractions. Eli Bendersky does a fine job of both laying out this "fundamental" problem of computing and the traditional approaches to solving this problem, namely: - OO programming with syntax for classes (syntactically co-located data with the operations on that data), whereby adding types is relatively straightforward (provided for syntactically); whilst adding operations requires changing function sets or "interfaces", which in general requires more than merely adding functions, impacting (undesirably) the type declarations (classes). - functional programming inverts this ease of modification aspect, since operations are the first order syntax, which thus leads the programmer to design his program with functions/ operations as primal, thus adding functions is the simple program extension mechanism just like adding data types or classes is the simple OO extension mechanism; whilst adding new data types in the functional language requires all existing functions to be (again, undesirably) modified to handle the new data type. The same "expression problem" thus manifests from either side of the programming language spectrum. Velly interdasting. Bendersky lays it out clearly, and with nice little matrix PNG images, then goes on with the (relatively, at least in C++) complex "visitor pattern" which is typically used to solve this problem in C++, using virtual multiple inheritance and dynamic type checking - not the simplicity we crave for our programming solution baskets. Enter the White Knight, Clojure, with syntax so powerful only Lisp dialects raise their heads in a collective superiority sneer. The secret? Clojure syntactically hides multiple dispatch behind reasonably elegant syntax - so the performance hit is there, but at least achieving the result is not a syntactic nightmare of virtual multiple inheritance + RTTI functionality or some ungodly template syntax. But it's actually only single dispatch? Yes, there be more lurking secrets - what Clojure calls "open methods": “Note a crucial difference between how methods are defined in C++/Java and in Clojure. In C++/Java, methods have to be part of a class and defined (or at least declared) in its body. You cannot add a method to a class without changing the class's source code. In Clojure, you can. In fact, since data types and multimethods are orthogonal entities, this is by design. Methods simply live outside types - they are first class citizens, rather than properties of types. We don't add methods to a type, we add new methods that act upon the type. This doesn't require modifying the type's code in any way (or even having access to its code).” Clojure "protocols" (from Java POV, "simple, usuall single-method Interfaces) also get a look in. Here's the source, Luke: The Expression Problem and its solutions https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions/ Bendersky even does a second round - recommended: More thoughts on the Expression Problem in Haskell https://eli.thegreenplace.net/2018/more-thoughts-on-the-expression-problem-i... So notwithstanding that Clojure runs on the JVM, note Java's first class syntactic citizens are classes (in comparison to Clojure's first class functions): java - What is a first class citizen function? - Stack Overflow https://stackoverflow.com/questions/5178068/what-is-a-first-class-citizen-fu... “So, objects are the first class citizens in java. Admittedly, java8 supports passing of methods (method behavior, to be precise) to other methods using functional interfaces and lambda expressions. But that does not mean that java has functions as first class citizens.” Note that Java 8 syntactically adds "first class functions" which are represented internally/ in the JVM, as classes (perhaps this is how Clojure runs on the JVM?): Java 8: Simple Example of First-class Functions http://4dev.tech/2015/08/java-8-simple-example-of-first-class-functions/ (Observing Java's predicates and other such Lisp wanna be syntax, it's rather fugly IMEHO.) The link to Bendersky was highlighted by Stephen Mann in his this week's mailing list mailout, where he also links to his recent blog on "good names" in programming: Good Code Depends on Good Names https://stephenmann.io/post/good-code-depends-on-good-names/ I can't find his email list archives, but here's his blog index: http://stephenmann.io/