By relieving the brain of all unnecessary work, a good notation sets it free to concentrate on more advanced problems, and in effect increases… mental power — Alfred North Whitehead
Programming languages are for people — not computers. Computers don’t need any programming language other than machine code. Good programming languages help make problems easier for people to reason about. This is important because writing code is not just about solving problems. It’s also fundamentally about how you think, communicate, and comprehend.
On the web today, we have one, dominant language: JavaScript. JavaScript was created because Marc Andreessen, “believed that HTML needed a ‘glue language’ that was easy to use by Web designers and part-time programmers to assemble components such as images and plugins.”(1)
As front-end developers, we should not accept this. We should not allow ourselves to be restricted to one language — especially not a language, famously cobbled together in ~10 days that only has some “good parts”. While Axel Rauschmeyer (for whom I have a lot of respect) may believe that it’s a good thing for JavaScript to be a mess — I couldn’t disagree more. We need languages that help us solve problems — not languages that create more problems for us to solve.
“The words available in a programming language for expressing your programming thoughts certainly determine how you express your thoughts and might even determine what thoughts you can express.” — Steve McConnel
There’s an old joke that goes something like this.
In Heaven: the cooks are French, the lovers are Italian and the bankers are Swiss.In Hell: the cooks are English, the lovers are Swiss and the bankers are Italian.
Along the lines of this joke, if we want to write well about cooking, we should write in French. While we might be able to write about cooking in English, we would be lacking in the vocabulary and paradigms present in French that are essential to cooking. And, in fact, if you know about cooking, you know this is true! There are many terms central to cooking that are specifically French. Even if you are writing an English cookbook, you use these French words (e.g., mise en place, Bain Marie, Coulis, &c.).
The language that you work in has an impact on the way you think about and solve problems. To illustrate this, let’s compare how currying works in Haskell with how it works in JavaScript. We’ll consider a simple currying function.
Here’s the Haskell code:
In Haskell, functions are automatically curried. Currying is part of the Haskell paradigm. As a Haskell programmer, I know this. It influences every bit of code that I write. The way that I think about how to create a function — i.e., solve problems and communicate — involves currying at some level.
Here’s some JavaScript code that does more or less the same thing(2):
Currying is not implicit in JavaScript. If I want to use currying, I have to implement it. Then I have to use it explicitly. And there are a ton of implementations— not counting the possibility that I might choose to implement it myself. Each implementation comes with its own costs and benefits.
Because I don’t have native currying, I’m having to deal with decisions I wouldn’t have to make in Haskell. In fact, if I’m trying to do Functional Programming in JavaScript, I may have to make many decisions like this. Each decision impacts my problem solving, and my code in several ways:
As you can see, even from one small example, there are significant differences in the way that Haskell and JavaScript approach the same task. What is trivial and innate in Haskell turns out to be more involved, verbose, and alien in JavaScript.
To sum up, we can state our own version of Whitehead:
A good programming language, applied to the appropriate domain, can increase your problem solving ability. A bad language — or one that’s a poor fit — can make things harder.
Knowing the impact of a language on problem solving and communication, it should come as no surprise that programming languages are often created to solve specific problems. A few examples:
Modern web apps are written to solve a wide variety of problems. We should have a diversity of programming languages. We should be able to work with languages that were designed for our problem space, that fit our way of working with problems, or that we want to learn something from.
In short: It’s time to break free from just JavaScript.
Even though JavaScript is the only language supported by modern browsers, we can work with a wide variety of languages to build web applications today. Thanks to the work of many, well-supported projects there are a wealth of languages available that compile to JavaScript. There are even projects that support using those languages with popular frameworks like React and Vue — for example, Reason-React, PureScript-React, Reason-Vue, and others.
For a fairly comprehensive list of languages that compile to JavaScript, see Jared Ashkenas’ GitHub list. The list includes all of the .Net languages, Scala, Haskell, Ruby, Elm, Python, Erlang… and on, and on. The number of languages represented on Ashkenas’ list is so large that it suggests a companion to Atwood’s law: “If a programming language exists, someone will write a tool to compile it to JavaScript.”
While there are a TON of languages that compile to JavaScript, this is not a perfect option. Compiling to JavaScript comes with known issues:
Innovation always comes with a cost. So does stagnation. The costs of stagnation are higher. If we’re going to make progress in front-end development, we must have more diversity. Someone needs to lead the way. When there are enough developers who use a given language in the web app space, there will be a motivation for the tool creators, vendors, and community to give their support. Even if we only end up with two or three dominant languages, we’ll have richer vocabularies and paradigms to work with.
Notes