Two More Cents

Similarities between Programming Languages and Spoken Languages

Over the last few days, I worked on a presentation for my introductory German course. We got to choose our topics for this presentation, and I decided to do mine on Football (Soccer) in Germany. I had a lot of fun doing it, and I think it turned out pretty well. As I prepared the speech for the presentation though, I couldn’t help realizing the similarities between learning a spoken language, and learning a programming language (for context, I’ve also been learning Go over the last few weeks).

You Start Off With Phrases

I remember the first couple of days of my German course. We started learning phrases, such as greetings, introductions and good-byes - “Guten Tag”, “Wie Geht es Ihnen?”, “Auf Wiedersehen” etc. At the time, I didn’t really understand what the individual words meant - just that, if you wanted to say “Good Day” to someone, you said “Guten Tag”.

Unless you’re one of the few people that built a completely ground-up understanding of how computers work (NAND2Tetris comes to mind), you probably had a similar stage when you learned a programming language. Hell, the first program you write is even called “Hello World”!. An example that comes to mind is when I learned C - I didn’t really understand what #include at the top of my program did. All I knew was that if I wanted to print something or take user input, I stuck #include <stdio.h> at the top of my program.

History Helps

One of the things I like about German (so far) is it’s consistency - forming compound nouns, for example, is often intuitive, and they usually mean what you think they mean. In contrast, I often hear people crapping on English’s inconsistent naming conventions, especially with food. I used to be one of them, until I watched an OverSimplified video that discussed it. Understanding the history of England, with the Anglo-Saxons and the Normans, helped me understand why English is the way it is, and why German doesn’t have any of its idiosyncrasies.

An almost identical lesson can be learnt by studying the history of a programming language. Learning why language developers made certain decisions, why they made them, and the status quo that they were trying to fix has been immensely helpful in my experience. Specifically in the case of programming languages, it also helps you identify the domains in which a language shines.

Grammar is a Framework

Most rules surrounding German grammar are similar to those in English- the ‘Subject Verb Object’ order, for instance. But German has a very strict ‘Verb Comes Second’ rule, which leads to weird sentences, from an English-speaker’s point of view. For example - “Täglich gehe ich zum Markt” (translated word-by-word: “Everyday, go I to the market”). However, once you get used to it, it makes the process of reading and parsing sentences a lot easier. In comparison, certain languages have very loose rules regarding grammar, with colloquial usage often playing fast-and-loose with it.

In a similar vein, programming languages have certain rules around grammar as well. These rules can often help the programmer understand what’s going on in a program, as every program must obey these structural rules. For example, Go has the func keyword to identify functions. In order for your code to be valid Go, this keyword must be used with every function. This has the effect of making all functions easy to identify - a quick glance at a program will tell you which blocks of code are functions, which inputs they take, and which outputs they return.

The Importance of Being Idiomatic

Obviously, I am far from being a ‘native’ German speaker, so I’m not aware of the phrases and colloquialisms that Germans use. But as a native English speaker, there are a number of idioms and phrases, which are hard to translate literally. “Out of the blue” is one that comes to mind. “To hit on <someone>” is another one. The usage of such idioms and phrases are often what distinguish native speakers from non-native ones, regardless of their skill level in the language.

This has strong parallels to idiomatic programming - Writing a Go or Rust program is one thing, writing one in the style of Go or Rust is an entirely different matter. I can take everything I learned from Java, and give my C variables obtusely long names, and create Getter and Setter methods for everything, or I can do it ‘the C way’. The idiomatic way, just as in spoken languages, is only learnt with time and exposure to the language.

Somewhat related is a question that was explored in the StackExchange Linguistics forum - ‘Do multilinguals have one language they predominantly think in?’. It’s an interesting one for me especially, because I have native fluency in two languages - English, and my native mother-tongue of Tamil, a South Indian language. Depending on the scenario and context, I often switch my ‘language of thought’ between both languages.

I think programmers who know multiple languages often have the same experience - The problem you are solving might require you to think in a certain language, even if you write your program in a different one. Programmers are often restricted by their employer (or in my case, course standards) in the languages they can use, but in your mind, the only limit is your knowledge.

My Workflow for Written vs. Programming Languages

This was actually the experience that prompted me to write this post. As I was writing my German speech, I realized that my workflow followed a pattern -

  1. Write a few sentences in German, in a Word Processor.
  2. Read them again, to see if they make sense.
  3. If I want to use a verb or noun, but I don’t know the German word for it, I use a German-English dictionary. (Tangential, but I’ve found LEO to be very helpful).
  4. If there are entire sentences or concepts I don’t know how to express in German, I often turn to Google Translate (after checking that it makes sense, of course!).

Compare this to my workflow while programming:

  1. Write a few lines of code, or a function, in an IDE.
  2. Read the function again, to make sure that it does what it’s supposed to.
  3. If there is a specific method that I want to learn about, I consult the documentation for the API that I’m working with (or the Standard Library).
  4. If there is some operation that I want to do (think In-Order Traversal of a Binary Tree), but don’t know how to do, I consult ChatGPT (after checking that it makes sense, of course!).

See any similarities?

I’m sure this has been covered more exhaustively elsewhere. Shoot me an email if you think I left out any similarities.