Go is…? (Beyond Paradigms)

A few days ago, I posted an attempt at explaining Go on social media. The post was inspired by a question I got in a Reddit thread: “Go is neither an OOP language nor an FP language. What is it, then?” I answered that Go is kind of “OOP minus inheritance, with a bit of functional programming.”

Object-oriented, functional, procedural: paradigms galore!

It's human nature to put everything into categories, into mental compartments of varying granularity. The world is easier to grok this way. Friend and foe, male and female, black and white, us and them. But the world doesn't work this way. There is always a spectrum between two categories, and beyond.

And so, the IT world invented tags to slap on programming languages. Procedural, object-oriented, functional, imperative, and whatnot. Surely, these tags (known as “programming paradigms”) help clarify the mental concept behind a language design and the programming style the language supports best.

Paradigms are only a crutch

The problems with this approach start with the very definitions of these paradigms. When is a language object-oriented? When is it functional? Ironically, the language LISP, widely considered a functional programming language (since it originates from a mathematical approach to programming, influenced by lambda calculus), is the first language associated with object-oriented programming. Defining object-oriented languages as “having inheritance” is a popular myth. By the most minimalist definition of object orientation, an object-oriented language only needs to support abstract data types—objects that have an internal states and methods that query or change that state. Another definition that gained some popularity was coined by Alan Kay. Asked about his understanding of object orientation, his answer was:

“OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.

The functional programming paradigm is also fraught with ambiguities. For Functional Programming purists, a functional language is truly functional if it supports only pure functions with no side effects whatsoever. With this definition, LISP is not a pure functional language.

Multi-paradigm languages?

In fact, Wikipedia designates both Go and LISP as “multi-paradigm languages”. Go is characterized as concurrent, imperative, functional, object-oriented, and LISP carries the tags functional, procedural, reflective, meta.

Wait a minute—Go as a functional language? News to me.

Sure, Go's functions are first-class citizens. You can assign them to variables or pass them to, or return them from, functions. Functions can even have methods. But this single aspect doesn't make Go functional. And Wikipedia isn't even in agreement with itself about the paradigms Go covers. The page Comparison of multi-paradigm programming languages lists Go explicitly as neither functional nor object-oriented.

And what's a “programming paradigm” anyway? Look around at that Wikipedia page. There is “functional”, “procedural”, and “object-oriented”, but also “pipeline” (which I would consider syntactic sugar), “distributed” (an architectural concept, rather than a language design concept), or “visual” (a fancy, interactive user interface on top of a procedural, dataflow, or other kind of language).

Moreover, Go and Rust may share the same paradigms, but their approach to memory management—automatic versus manual (compiler-guided)—is perhaps the biggest distinguishing feature between the two languages. And this is not even listed as a paradigm.

Programming paradigms are obviously not an optimal way of categorizing languages.

Programming languages are like spices

Curry powder, Garam Masala, Ras el Hanout, Café de Paris—all these are blends of various spices. The particular combination of individual herbs and spices gives these blends their unique taste.

Programming languages are no different. By combining aspects from various programming paradigms, language designers create a unique programming experience.

Shouldn't we better talk about a programming language like a “spice blend” of fundamental features, rather than only looking at the mishmash of paradigms that fully or partially apply to the language? Features instead of coarse-grained categorizations. If nothing else, at least it provides fewer incentives for language advocacy.