Why Some Programming Languages Win
And others loose.
It's no secret that we at Coraid run pretty much a C monoculture. That's for several reasons that I won't go into here. C has clearly been a winner of system languages, knocking down all but one other language, if the popularity contest web bots are anything to go by. (Java rivals it. They have switched lead several times over the years, but C still hangs in there strong.)
But there really was strong competition when Dennis Ritchie invented C. When started by adding types to the language Ken Thompson has invented, and called it C, there were several languages all competing for replacing the use of assembler languages for writing compilers and operating systems.
The language Ken had invented was known as B. The year was 1971. The Labs had installed a PDP-11, and Ken had transliterated the first Unix kernel from the original PDP-7 assembler into the PDP-11's machine code. It was around then that Dennis took up the B compiler to get it to emit code for the PDP-11.
There were other languages in 1971 that could have grabbed the lead spot from C as the best systems language. One was PL/I. IBM had created the language only a few years earlier as a ``do everything'' language. It combined features to allow business programming, scientific programming, and systems programming, all into one almost impossible to understand tangle of conflicting features. Actually, I exaggerate. It wasn't that bad--just large.
PL/I was supposed to replace COBOL, FORTRAN, but it really did neither. My theory is that it was exactly because it was large that it was difficult for the rank and file business and scientific programmer to learn. Most scientists were not really interested in complex language constructs, and anybody can learn COBOL. Learning PL/I is a different thing altogether.
But history shows it was clearly a sufficient programming language to write operating systems. MIT's project Multics was written using a PL/I compiler developed by some of the very people who later would work on Unix. They got around the problem with the largess of the language by implementing a subset. Bell Labs pulled out of Multics project in 1969, and Ken and Dennis went on to develop Unix, in spite of Bell Labs management directing the researchers in no uncertain terms to avoid any research on Operating Systems.
Not only was Multics written in PL/I, but a good deal of the most successful operating system in the world, IBM's MVS, was written in it as well. Or I should say rewritten. And they used their own subset to do it.
MVS was piece by piece rewritten in something they called BSL, Basic Systems Language. Later, BLS was renamed PL/S, a much simplified language designed to only do what was needed. It was in a tradition that has often happened in computing. Ken's language B was based on a language called BCPL, which was Basic Combined Programming Language, itself a reduced CPL, an Algol like language that was never written.
IBM's BSL was described in a manual of only 70 pages, including the index. It obviously omitted a great deal of the complexity that hamstrung the adoption of the full PL/I language. BSL had some recognizable features later embodied in C. It included pointers, structures, and used the now familiar "->" qualifier to use pointers to structures. They even used those very names. They also had an include facility. They called it "%INCLUDE" instead of "#include" of C, but what's a pound or percent among friends. All this was several years before B or C.
But PL/S had two characteristics that seems to me to have doomed it. The first was that IBM would not let the language escape the confines of their development laboratories. I don't know if this was because they worried about it competing with the full PL/I, or they thought it was so valuable it should remain restricted. I tried to get a copy of it back in the late 1970's when I had my office down in the UGA Data Center. No dice.
It had some other problems as well. One could see the IBM mainframe instruction set shinning through the language. There were procedure options that would tell the compiler which registers to save, and which to use. One could use a GENERATE statement and emit raw assembler output, much as the "assem" feature of some C compilers. Things such as those killed the BLISS programming language developed a couple of years later at Carnegie Mellon for the PDP-10, a 36-bit DEC mainframe. No PDP-10, no BLISS.
But I think the biggest reason PL/S would never have won the competition to replace assembler in systems programming was the feel of the language. It was a collection of statements glued together with a simple sequence concept. The language description, instead of being described in a context free grammar, like BNF, consisted of what looks like Unix command usage syntax. This language description notation was very similar to the COBOL syntax. And it betrayed a lack of linguistic structure.
The reason for this is that it was not a clean, clear idea like C.
C consists of expressions of 42 binary and unary operators in 15 precedence levels with only the barest of control structures around it. It is defined with a grammar that is easy to parse. Dennis' first compiler used a technique called operator precedence and simple recursive descent for the data declarations and control structures.
Let me give you an example of what I'm talking about. In PL/S, you could group a number of statement with the keywords "DO" and "END." They must be followed with a semicolon, since they were "statements." In C, the curly braces do the same function, and are integrated into the grammar of the compound statements. No semicolon required. In BSL, they are statements that semantically statements. In C, the curly's are special to the syntax.
But the fact that everything is an expression is so clean, that it makes C, as low level as it is fantastically expressive. Even the assignment is an operator in C. The rules for control statements being simply integer expressions mean that even the equivalency operators are just binary operations. All this makes PL/S seem a bit stale for systems programming.
Another way that C is better than all other competitors of the day, and something poorly understood today, is that it only does what the machine does. It was meant not to require a large runtime library. The best example of this is the lack of strings in C. They were left out for the simple reason that there are no strings native to the underlying machine. Sure, there is a group of characters surrounded by double quotes, but this is just a convenient way to initialize an array of bytes and put a null character at the end. You have to call a function to actually tell if two strings are equal.
Why is this beneficial? Because with C, unlike all the competing languages of the day, you completely know what's going on. Nothing is hidden in some runtime routines. You don't need to be the person who write the compiler and runtime to understand everything. This is indispensable if you are trying to make thinks like operating systems, or even embedded network storage system go really fast even on really cheap hardware. Most of the other competing languages had large runtimes and abstractions that were much higher than provided by the machine.
There are a lot of other things I could mention as well, like no I/O built into the language. Neither was there features for multi-threading, or interrupt handling. These could all be done with the language without having to define these into the language. They filled a much needed gap.
What Ken and Dennis did in inventing C, was to create a simple language, that was easy to implement, easy for anyone who knew the assembly language for their (or any other) machine to learn. It was one that could be fully described in only about 28 pages of the K&R 1st Edition. (I'm referring to the reference chapter.)
All languages after C took most of their ideas from it, curly braces, for example. Java owes a lot to C. In fact, using Java requires a C program. The Java compiler, which is written in Java, is a byte code program. The JVM has to execute the Java compiler, and the JVM is written in C. You can't run byte code without the Java virtual machine.
So, in the end C won. There are other programming languages being used, but almost all of them are written in C. Will this be true forever. Well, nothing lasts forever. But I've yet to see anything that is as clear an elegant as C. Almost nothing. Oberon is still my favorite programming language, by a nose.
But that story is for another day.
Computer Scientist
5 年The simplicity of C is what made it not only powerful but extremely flexible. If all of the standard libraries had been built into the actual language, I for one might have had a devil of a time replacing the Qsort subroutine with my incredibly faster pev_qsort version. Being able to replace or front end any of the language features allowed it to evolve and grow.
VP Technology, CRISPR QC
5 年Did I just find another corner of the Internet that's giving you credit for inventing the whole thing? NAT this time, hmm? Radia might be upset! https://www.quora.com/Who-invented-Network-Address-Translation-and-how-was-it-first-used
I used C during my college/professional time in my country, El Salvador, and I remember when I was taking Operative Systems class, that I decided to learn a little bit more how to control interruptions and the video memory, since I was amazed by how TSR (Terminate and Stay Resident) programs were working, C was the tool that took me on that trip, books at the library showed me how to insert my own small functions to do something else when an interruption was called, something that even my C teacher told me at that point: "boy, I don't know what are you doing here!!" I learned that managing the video memory was thousand times faster than using the graphic libraries in the C compiler at that time (thanks Borland Turbo C) and when I worked for the government in my country, I design/wrote and ran for a couple of years a program (you got it, written in C) to parse the information of all the citizens in my country that were saving for their retirement programs, this was an elegant and fast data structure using pointers. Now, I use different languages to do my job, but I will always remember that I probably won't be here if it wasn't because of the C language. And as I always said, we never know what the future is preparing for us, I might go back to C one day.
C was my first serious programming language, and I owe it a lot of my style. Nowdays I am more in system administration roles and have moved to Python, after a while coding in Perl. I've tried other languages (Java, Ruby, PHP) but none has hooked me like the C I learnt my first year in college. C is definitely the king , and the only one I would use to program operating systems.
C ??