There is a myth in the software industry that anyone who knows a C-like language can easily pick up another C-like language in a week or so. That is simply not true. For one thing, everyone knows that a language is more than its syntax and that being productive requires learning the entire ecosystem around it – standard and de facto libraries, build tools, debuggers, etc.
More importantly, learning a language is only the first step on the way to actually knowing it. To help illustrate the difference, I figured I would make a list of all of the programming languages I have learned over the years and another list of the ones that I know.
Programming Languages I Have Learned1
All of those languages I have used in some form or another. I have written at least one program with them. In the cases of the most recent ones, I have read books on them and sometimes even the language spec. I am by no means an expert with them; I don’t even have much experience with them. But I have learned them.
And now, here are the languages that I know.
Programming Languages That I Know
Really? Just one? Yeah. Just one.
What It Means To Know A Language
To me, truly knowing a language goes beyond just being able to open an editor and type fluently. It means that I understand how the language internals work; how the language interacts with its runtime environment; how it handles memory allocation and garbage collection; and what are its idioms and idiosyncrasies. I know the “best practices” and when to break them, how to efficiently debug a program in that language, and where the pitfalls hide.
It takes a lot of time working with a language in real world scenarios to really know it. And that is fine. As Peter Norvig pointed out in his essay “Teach Yourself Programming in Ten Years,”
The key is deliberate practice: not just doing it again and again, but challenging yourself with a task that is just beyond your current ability, trying it, analyzing your performance while and after doing it, and correcting any mistakes. Then repeat. And repeat again. There appear to be no real shortcuts.
There appear to be no real shortcuts. There’s a life lesson for us.
Why Learn So Many Languages Then?
In a phrase – diversity of perspective.
The most important aspect of learning different languages is to open your mind to new ways of looking at the same problem. When you solve the same problem over and over again, such as writing a web app, in different languages, you learn the cost and benefits of different tools and methods – where does static typing help and where does it get in the way, for instance. And if you approach the language learning process with an open mind, you can bring back some of those benefits to your day-to-day language, even if it does not explicitly support the features.
A language that doesn’t affect the way you think about programming, is not worth knowing.
When I studied Scala, I learned about co- and contravariance. These concepts are obfuscated in the generics system in Java, so while I know how to use generics, I did not fully understand what they meant until learning Scala. Learning Scala helped me better understand the design trade offs I needed to make when I was writing Java classes.
the use of
const, a direct parallel to Scala’s
const, I use them as an indicator of intention in my code so that
when others or I read it later, we can easily scan and know whether a variable
is meant to be changed or is expected to always be the same.2
The Practice of Learning
Another benefit of learning new languages is that it is a way to practice learning. Contrary to the myth mentioned at the start, learning a new language is not an easy week-long exercise, unless all you want to know is the syntax (and even then, with some languages, a week is not enough). It takes practice to be able to pick up a new language quickly. So, you have to practice how to learn. Do you read the language spec? Do you boot up a REPL and start playing? Do you have a project you implement repeatedly to directly compare multiple languages? Exercising your brain to learn languages will make it easier to learn more languages in the future, and in our fast-paced world, that will always be beneficial.
Furthermore, some of the concepts in some languages are really hard to understand, so the learning part takes some effort. I’m reminded of the several new types of types3 that I learned in Scala and the concept of monads I was introduced to by Haskell. Fortunately, many of the language design concepts are repeated over and over again, so when you learn several languages, you can draw connections between them and use what you learned in one to more quickly learn another. After learning about algebraic data types in Haskell, I instantly knew how to use them when I encountered them in Elm. I was also able to draw a quick parallel between monads in Haskell and ports in Elm, even though they are not the same thing. Learning the first made understanding the second easier.
Learning New Things
Some languages teach you entirely new concepts in computer science. Before learning Clojure, I did not know about persistent data structures at all. Rich Hickey, the author of Clojure, didn’t invent them, but he used them in order to efficiently uphold a fundamental principle of his language, that all data structures be immutable by default. If I had not bothered to learn Clojure, I may not have ever bothered to learn how persistent data structures work.
My third example comes from the world of Scala. There was a fair amount of discussion and research into software transactional memory when I was studying Scala, and a couple years later when I learned Clojure, I interacted with its refs, along with non-STM atoms and agents, primitives meant to help with concurrent data access that are built on STM concepts.
These are three very powerful constructs in the modern world of computing that I may not have learned if I had not been learning new programming languages.
What’s It All For?
So, learn new languages. Not to pad your resume, but to pad your brain.
For the purposes of this exploration, I am not counting domain-specific languages like SQL, HTML, or CSS, which I do happen to have both learned and know. I’m also not counting “regular expressions” which are essentially a language of their own. Furthermore, I’m not counting languages that I “learned” just enough of to accomplish a very specific task, such as Python, PostScript, and TeX. ↩
I had been using a similar technique in Java for years thanks to the
finalkeyword. I littered my code with it –
finalvariable declarations. But it signaled intention, and thanks to a static environment, it was enforced by the compiler and runtime. ↩
Scala includes the notion of existential types, which is a mechanism to indicate that there is a type involved in the expression but what type it is doesn’t actually matter right now. And I thought only humans had issues understanding their true meaning in life. ↩