System.out.println(“bonjour tout le monde”)
No wait, that was terrible. Let me say that again.
print “hola mundo”
I apologize, I should have said,
Most of us have learned how to create this toy program in many languages. But have you ever considered which one is the best?
Expressing the ubiquitous “hello world” example in Java takes, in addition to the phrase being printed, 20 characters. Doing so in Python and C requires only six and eight, respectively. If one were to judge these languages purely based on verbosity, Python would emerge the victor. Any number of other measures could be devised upon which to rate the quality of this program and each measure could produce a different result.
But suppose we focus on the wordiness metric and extended that comparison to the phrase being printed. Between the three languages used, Spanish would be the most concise, followed by English and French. Imagine somebody were to declare Spanish the best language on this basis. Would this seem a reasonable assertion or one that overlooks the form, function, utility and nuances of every other language?
I firmly believe that there is much we can gain from learning to understand programming problems not for a language used to solve them, but for the idea being expressed by the syntax. Engineers can become problem solvers rather than enthusiasts of one form of expression by understanding the strength in speaking as many dialects as possible. Nearly any idea can be expressed in any spoken language, but the delivery and nature of expression varies between them. And while the manner of expressing an idea will vary among languages, the idea itself transcends the implementation.
As I have grown as a software developer and learned new programming languages, I have grown to admire those who can do the same with foreign languages. Though the power and flexibility to express the same idea in different spoken languages is obvious, I believe the corollary for computer science is easy to overlook.
First, some context for this perspective. In my formative years working in a large company, I encountered my share of those who sought to declare a language, framework or technique superior to all its competitors. In fact, I have probably done this myself.
You have undoubtedly met — or have been — somebody who committed this cardinal sin of the church of language agnostics. Much as we tend to think in our first language, some engineers tend to become attached to their first language.
It did not take long in my career for me to meet some very intelligent software developers who helped me form a better perspective on languages. Through working with some of these individuals, I learned to approach software problems not by solving it in a language, but by solving the problem first then expressing the solution in a language.
Through this experience, I began to realize there are many parallels between spoken languages and programming languages. Language is a form of expression and, like any art, there are strengths, weaknesses, and nuances to any form of expression. Are Romance languages superior to Sino-Tibetan languages? Are those which arrange their sentence structure in the subject-verb-object better than those which arrange them in a subject-object-verb order?
The universality of computer science problems logically extends to other forms of expression. Are oil paintings more fulfilling than charcoal? Do still images inspire greater imagination and wonder than video can ever hope to? Is it better to read the book or see the movie upon which it is based? Or can they all convey the same (or similar) idea by using a different implementation of expression?
This does not mean to ignore the nuance which can be lost when translating an idea between languages. There are countless phrases which are difficult to provide direct translations for among languages. Even among Western tongues this occurs quite often. For instance, the German word Kummerspeck has no direct English translation but is meant to express the “excess weight gained from emotional overeating.”
This should sound familiar to anyone who wrote “a” for each loop in Java first then had the chance to write it in Python, Ruby or even Groovy. Heck, even between differences of Java (I’m looking at you, Java 1.5 and below), “the” for each loop was different, but the idea remained the same.
Objectively Approaching Problems
In a recent study, researchers from the University of Chicago and Pompeu Fabra University in Barcelona studied the effect of language on an individual’s decision-making process. This study asked participants to respond to the trolley problem. This problem presents the participant with a hypothetical situation in which they could act to save five people at the expense of one. But to save the five, the participant would have to forcibly push that one person to their death. While there are many permutations of this problem, the purpose of posing the dilemma is to gauge an individual’s perspective on morals.
Though much research has been performed using this problem as its focus, the researchers decided to modify the experiment and ask similar questions in both a participant’s native tongue and a non-native tongue. Their research revealed that
“[W]hen people are presented with the trolley problem in a foreign language, they are more willing to sacrifice one person to save five than when they are presented with the dilemma in their native tongue.”
The study effectively found that people would make more utilitarian choices in non-native languages while those they were asked to make in their native tongue gravitated towards the emotional.
As engineers are wont to do, decisions should be made based on data and with the desired goal in mind. In an ideal world, the decision-making process should be a dispassionate exercise where the chosen route is influenced only by the desire to find a best solution.
Reading the research study caused me to take inventory of my own approach to programming problems.
This became such a habit that I decided to solve problems best suited for scripted languages using Java. I would battle with Java to get simple web applications set up when all I really needed was a lightweight web framework for small programs. I unconsciously refused to try other methods to perform tasks as simple as parsing JSON.
Polyglot is a Four-Letter Word
Multi-language acuity is typically referred to as being a “polyglot” programmer. I have never been in favor of this term because I believe it is not only an oversimplification of a greater idea, but also reductive of the person who truly fits this description. Understanding how to program in multiple languages is not a skill that needs to be packaged in a dazzling term to be slapped on a CV or requested in a job listing. Instead it should be one that manifests itself through an engineer’s ability to be flexible and able to solve problems in the best way possible.
Do you need to write a quick script to fix the contents of a database or text file? Sounds like a scripted language is a good place to start. Need to build a scalable REST service with high availability? Go with a strong server-side compiled language. Have to slam together a quick web UI to communicate with that REST service? Try a lightweight server-side language combined with a client-side UI framework.
But just because you have to choose one language for the task doesn’t mean you need to be a native speaker of that language to do it. With the resources available to any engineer today, there’s a fine line between being a native speaker and one that can effectively Google their way to the syntax. Nobody grew up knowing the right way to System.out.println. Try a new language once in a while and take the time to appreciate the form the solution takes in an unknown syntax.
Language Promiscuity is a Means, Not an End
This is not to say that learning a language well is without merit. In fact, obtaining an intimate understanding of any language can pay dividends. But, at a minimum, good engineers should place themselves in a situation where they are forced to live outside of the comfort zone of their syntax of choice.
Depending on your abilities, it may be counterproductive to spread too wide a net. Personally, I can keep only a few languages in my field of view at any given time. But I try to strike a balance as best I can.
Learning new languages should be a means to better understand computer science problems. That balance should be struck with this goal in mind. Pick up new languages as often as you can, but bear in mind the ends this effort is designed to foster.
Solve the Problem First, Then Express the Solution
I try to bear in mind that I should not try to solve problems using a specific language but instead solve the problem first, then express the solution in a language (or framework within a language). I periodically evaluate my approach to the problems at hand in an effort to determine if I am relying too much on one technique or language to accomplish my goals.
Most problems can be solved in any syntax, but the choosing the right solution is almost always dependent on factors other than personal preference. Some of my favorite thought exercises involve imagining the same answer expressed different ways.
There is something wonderful about being able to express an algorithm for binary sort, design an interactive website, or say “hello world” in many programming languages as there are ways to say “hey there world” in spoken languages. After all, none of the syntaxes are the “best”–but it’s so satisfying to say it in as many ways as you can.