Three Funerals In The Name Of Clarity (Part 1: Functional)

27 Feb 2018

Oh right, I have a blog.

I’m making a resolution to myself: I will no longer use the following terms to describe programming languages, unless my intention is to not be understood:

These terms have no place in a rigorous technical discussion. They are wishy-washy in the same way that most words in most natural languages are.

But but surely it’s fine to draw on them in informal discussions, especially when we’re just “talking shop,” rather than actually trying to get anything done?

I’ve waffled on the latter point, but increasingly my experience has been that not only are these not “technically rigorous” terms, they are substantially less communicative that the vast majority of the English language.

I’ll tackle each of them as a separate post; while the consequences are the same, each of these terms has taken a different path to incoherency.

Today, we’ll talk about “functional” programming.

Every now and then I come across a statement like this one:

Rust is functional because it has pattern matching and strong static types.

Which I find so patently absurd that upon hearing it I am knocked off balance, and it takes me a moment to figure out where to even begin describing what’s wrong with it.

But as I pointed out above, these are wishy-washy meat-bag terms, not technical jargon, and I’ve heard this a number of times, so clearly my idea of what makes a functional programming language isn’t universal. So I shall get off my prescriptivist high horse.

What throws me about this is, I remember less than a decade ago that more often than not when I brought up the term “functional programming language” with folks, they had either never heard it before, or they immediately thought of Scheme. I discovered Scheme (and other dialects of lisp) quite a while before any language with types or pattern matching that billed itself as “functional.”

And yet here I am being told that these two features that my first “functional” language didn’t have are what defines the paradigm.

Back then, if you asked folks what defined functional programming, the answer was of course (first class) functions! I.e. lambda. Rust has those too. But nowadays every language does (even Java, finally). So clearly it can’t be the real criterion?

Hence we get linguistic drift; people start looking at other features that “functional” languages have, which differentiate them from non-“functional” languages. And so for many people the term “functional” basically comes to mean “like Haskell.” It is accordingly accumulating an alarming number of associations with things that are not lambda:

If linguistics has taught me anything, it’s that there’s no putting the genie back in the bottle. Like it or not, the word now means all of the above. So how do I, as a person looking to actually communicate, deal with such a uselessly muddled word?

Answer: Stop using it! If I want to talk about immutability, I’ll talk about immutability. If I want to talk about pattern matching, I’ll talk about pattern matching. If I want to talk about higher-order functions, I’ll talk about higher-order functions. If I really want to talk about “languages like Haskell,” I will talk about “languages like Haskell.”

Rather than continue to over-load the term until it actually doesn’t mean anything, I’d prefer we give “functional” programming a proper burial next to “structured” programming.

(Thanks to Story for coming up with a title for this series).