This is the first of a set of posts on what we need from a new programming language. Everything I discuss exists in some language – at least in part – but no language yet has them all. This content is a mixture of my experience and many borrowed ideas, which I will do my best to cite. My goal is to represent the language needs of some segment of developers.
The Metaphorical Mind
I’ll start simply: a language must be designed and taught with its users in mind. There is a psychology to programming which may explain why some languages get adopted and better ones don’t. To model this psychology, I borrow the idea of the “Metaphorical Mind”, as described in Steven Pinker’s excellent How the Mind Works. In Pinker’s words, “The human mind, we see, is not equipped with an evolutionarily frivolous faculty for doing Western science, mathematics, chess, or other diversions.” Our minds evolved to work with the physical world, and we reason with abstract ideas using physical metaphors. Pinker cites Ray Jackendoff for examples:
The messenger went from Paris to Istanbul.
The inheritance finally went to Fred.
The light went from green to red.
The meeting went from 3:00 to 4:00.
(emphasis in original)
The first sentence shows physical movement; the others use the same terms but have nothing moving. Beyond movement, spatial metaphors permeate our thoughts and language. “The meeting is at 3:00”, for instance. In fact, it’s hard to describe almost anything without physical metaphors.
Many examples exist in software. Imperative programmers deal with pointers, objects, stacks, messages, events and so on. Our secondary storage uses folders, files and paths.
In fact, there is an alarming predictability on language adoption: languages that strengthen the physical metaphor – or at least solve problems without weakening it – have found widespread use. Languages with weaker physical metaphors remain with a small base. Compare the adoption rates of object-oriented languages to their functional counterparts.
This might be an indictment of functional languages, since they are typical expressed in abstract mathematics rather than physical analogs. That is unfair. Functional languages can be built and explained in straightforward physical terms – they just aren’t. Take, for instance, Haskell’s Monad. I’ve written only small programs in Haskell, but for my purposes it’s much easier to think of a Monad as a “to-do list”. (Some use the term “action”. I know it’s an over-simplification, but that’s the point.) The bulk of the language is a means to construct to-do lists in isolation. Put in these terms, Haskell can be simpler than many languages – the functional purity eliminates all kinds of moving parts imperative programmers have to worry about.
This is a good step, but widespread adoption means more than renaming of concepts. Unfortunately, programmers who find and learn functional languages are not representative of the population. I’m afraid we would lose a broader audience in the first hour of learning Haskell, as soon as they got to this:
fibs = 1: 1: zipWith (+) fibs (tail fibs)
Beautiful, isn’t it? One line of code for Fibonacci numbers, what amounts to built-in memoization, the ability to get and manipulate any sequence, and so on. But it also has only the weakest of ties to a physical analog. Non-trivial examples are much harder to understand. Sadly, an incredibly powerful tool for some is simply too abstract for others to use effectively.
Because of this and other examples, I doubt Haskell will ever be widely used despite all of its advantages. But this is okay – we need powerful tools for the hands of experts. What I want to see is a more accessible language borrowing the best ideas from Haskell and others. I wish I could use Monads every day, and am willing to sacrifice some of Haskell’s other power to achieve this.
This raises an important question: shouldn’t we raise our expectations of developers rather than take away powerful features? A valid point, which I will tackle this in my next post. For now, the central thesis of these posts should start to emerge: we need a language with the best parts of Haskell and others in a more accessible form.