I’ve been getting interested in learning more about development recently, and Albert’s post popped up at the perfect time! For anyone who’s never written any code, it’s a great introduction to what “writing code” actually means.
Maybe I should have started the whole Tech Tuesday series with a post on programming since that’s why computers were created in the first place! In fact, thinking about programming in many ways precedes the availability of actual computers to carry out those programs. At the time that Babbage was dreaming up his Analytical Engine, Lady Ada started to formulate how a general purpose machine would be programmed. That was almost 100 years before the first truly programmable machines were actually built! Much closer to that date but still before he had access to a computer, Alan Turing in 1936 described an abstract machine (the Turing machine) that he then proved could compute anything a computer can do no matter how fast or complex a CPU, how much memory, etc it has (aside: that does not cover what a quantum computer might be able to do if we ever figure out how to make one work).
So what does it mean to program a computer? Somewhat flippantly: programming is telling the computer what to do. But given the pieces that we have put in place we can define programming more precisely as: creating a set of instructions that the CPU can execute to achieve a desired outcome. That outcome might be the computation of a number, the animation of an object on the screen, the manipulation of a text or — and this is the beauty of programming — pretty much anything else one can dream up. In the process of executing the program, the various parts of the computer work together as specified by the program. Data will move around memory and maybe to and from storage. If necessary, I/O devices will be activated. Possibly data will be sent or received via a network.
How does a programmer go about creating the set of instructions? In the early days of computers this literally involved hand picking instructions from the CPU’s instruction set and manually encoding these so that they could be fed to the CPU. But because of the work of theorists and the desire of visionaries we rapidly wound up with programming languages that were more easily accessible to humans and could then be translated by the computer itself into the instructions for the CPU. One such vision had always been to program a computer using simply spoken language and with Siri and Android voice actions we now have that as a reality — people are quite literally telling their phone what to do.
Whenever you program a computer in anything other than the actual machine code (the bytes that represent the instructions and addresses) you are using some kind of programming language. So called Assembly Language is barely above machine code. It is mostly a set of acronyms for the instructions with some ability to refer to program and memory locations by a name as opposed to an actual address. A program called an assembler is used to translate assembly language into machine code. Because writing assembly is really picking instructions by hand it takes a long time to write programs but affords the ultimate control over what code is actually executed which can be important for some cases, such as parts of a device driver.
Anything that’s more expressive than assembly is generally referred to as a higher level language. Among higher level languages there is still a huge range though from a language such as C which is closest to the machine end to a language such as Prolog on the other (Prolog deals with logical expressions). Higher level languages require some form of translation into machine code. This is handled by programs known as interpreters andcompilers. As a first cut you can think of the difference between an interpreter and a compiler as the difference between having a simultaneous translator and a translated book. Essentially an interpreter reads the higher level language as it comes along and figures out what to do whereas a compiler takes one or more passes over the entire higher level language program.
In order for an assembler, interpreter or compiler to be able to do their work, the expressions in assembly or in the higher level language have to follow specific patterns which are known as syntax. That is of course even true when programming a computer in natural language in the Siri example above. If you say something completely ungrammatical, Siri will not know what to do.
I have found programming to be a deeply satisfying activity and will write lots more about it in upcoming Tech Tuesdays. When programming I can spend many hours without noticing the passage of time at all. Part of the satisfaction for me comes from how programming is a craft that combines writing and analysis/math in a wonderful way. But part of it also comes from the amazing amount of control I can exercise over machines which contrasts sharply with the many limits on control in the rest of our lives!