This is the first post in the Tech Tuesday cycle on programming.
Let’s begin with a simple observation: even though various human languages are quite different from each other they cover much of the same territory – the human experience. We have words for food and activities and threats and so on. There are different words in different languages and sometimes even the symbol set is entirely different (I am struggling to remember Mandarin for our upcoming China trip). But despite those differences there aren’t any things fundamental to the human condition that you can express in one language but not at all in a different language (note: fans of the Sapir Whorf hypothesis may object to this characterization and that’s worth reading when you have time).
Now in computer languages there is a precise and formal meaning to the idea that all languages can say roughly the same thing. This is known as Turing completeness after Alan Turing who discovered it. Turing came up with the simplest form of a general purpose computer in the form of a so-called Turing machine. You can think of the Turing machine as a kind of universal computer. Anything that could be computed by a Turing machine could be computed by a modern computer and vice versa. And any computation you can express in a modern computer language could also be expressed as program for a Turing machine. I said computation here on purpose because obviously this does not say anything about input/output devices (the Turing machine only has a tape). The upshot is that there is nothing that you can compute in Python or Lisp that you cannot compute in PHP or C.
That is not at all the same as saying all programming languages are the same though, just as saying that you can describe the human experience in pretty much any language doesn’t imply that the languages are the same. It just means that the limits of their expressive power are the same. So how do programming languages differ then? Here too looking at the human language is instructive. For instance, if I tell another sailor to “jump the main halyard” they will know exactly what to do because this is an expression with a precise meaning. I could of course also have given a lengthy description using general purpose instead of nautical English by saying something like “find the rope that runs from the top of the big sail to the top of the mast and then back down and then pull on it by jumping up and letting your weight help you." The former is much shorter and more precise but you need to know what it means. The latter is verbose but any English speaker can understand it.
A related difference exists in programming languages although it is more complicated. There are lower level languages such as Assembly and C and higher level languages such as Python and Ruby. Generally it takes fewer words in the higher level language to express the same thing than in the lower level language. But unlike the general versus nautical English example, code in lower level languages is actually *harder* not easier to understand for a human. The opposite is true for the computer though. The ultimate low level language is machine code which the CPU understand essentially directly but is completely incomprehensible for a human reader without a reference book. Conversely, a lot of higher level languages are quite readable for humans and many are designed specifically for human readability. We have automated tools for translating the higher level language into the machine language that the computer understands (more on these in a later post).
So why would anyone ever want to use a lower level language? It used to be that lower level languages resulted in much, much faster programs. Why? Because the computer understood them more directly and didn’t have to translate from a higher level language. As computers have gotten much much faster and the tools for translating higher level to lower level code have improved, that speed advantage of lower level languages has gone away for all but the most extremely time sensitive applications (e.g. realtime 3D graphics rendering).
There are more differences between programming languages that we will get to know over the next set of posts as we learn about such things as syntax, semantics and data types. In the meantime, let’s return briefly to the sailing example from above. As we saw, the sailing terms such as "halyard” have a corresponding definition using simpler English terms. Much the same is true in programming languages – they all have ways of using the “keywords” that come with the language to define new words that are more powerful. As we will see this is really the essence of programming: creating ever more powerful words. The most powerful word in the end is the name of the program itself. When you “invoke” that word (that too will have a precise meaning) it’s like a powerful spell the computer runs the entire program.