Straying into dangerous territory

This is the 2nd part to my previous post, Squeak is like an operating system.

It’s easy to get lulled into the notion when programming in Smalltalk that you can use it like you would a programming language that is separated from the OS, that uses libraries, and is only linked in by a loader. Indeed Smalltalk is a programming language, but more in the sense that Bourne Shell is a programming language on Unix, and you’re using it logged in as “root”. That’s a bit of a bad analogy, because I don’t mean to imply that Smalltalk is a scripting language that uses terse symbols, but the power that you have over the system is the same (in this case, the Squeak image).

In Unix, you manipulate processes and files. In Squeak, you manipulate objects. Everything is an object.

I had an interesting “beginner root” experience with Squeak recently, and it highlights a difference between Ruby (file-based) and Smalltalk (image-based). Some might judge it in Ruby’s favor. I was doing some experimenting in a Workspace. To further the analogy, think of a Workspace as a command line shell instance in X-Windows. I had been using a variable called “duration” in my code. It was late. I was tired (really interested in what I was doing), and I got to a point where I didn’t need this variable. Cognizant of the fact that in certain workspaces variables hang around, I decided I wanted to get rid of the object it was holding, but I was a bit spacey and couldn’t remember the exact spelling of it. I had already changed the code that used it. So I evaluated:

duration := nil


Duration := nil

just to be sure I got both spellings. At first nothing weird happened, but then I tried to save the image and quit.

I had forgotten that 1) all variables in Smalltalk begin in lower-case, and 2) “Duration” (with the capital D) is the name of a class. Smalltalk is case-sensitive. Instead of saving, I got an exception dialog saying “Message Not Understood”. I found the source of the error, and for some mysterious reason, a message being passed to the Duration class seemed to be causing the error. I inspected “Duration” in the code and Smalltalk said “Unknown object”. Alright. So it wasn’t the message. Still, I thought, “Huh. Wonder what that’s about?” I ended up just quitting without saving. I realized the next day the reason I got the error is I had deleted the Duration class from the image (in memory, not on disk)! I confirmed this by trying it again, bringing up a code browser and trying to search for the Duration class. Nothing. I thought, “Wow. That’s pretty dangerous,” just being able to make a spelling error and delete a critical class without warning.

What happened?

Say you’re using Unix, and you’re at the command line, and there’s a critical executable that Unix uses to calculate the passage of time, called Duration (I know this would normally involve using a time structure in C and some API calls, but bear with me). What I did would be the equivalent to saying, “mv Duration /dev/null”, and when the system tried to shut down, it couldn’t find it, and aborted the shutdown. I know this sounds weird, because I just said the image on disk was unaltered. Anything that is actively available as an object in Squeak is in memory, not on disk. The disk image is roughly equivalent to the file that’s created when you put your computer into hibernation. It’s just a byte for byte copy of what was in memory.

Unix treats directories/files, processes, and shell variables differently. It treats them each as separate “species”. One does not work like the other, and has no relationship with the other. I know it’s often said of Unix that “everything is a file”, but there are these distinctions.

Another fundamental difference between Unix and Squeak is Unix is process-oriented. In Unix, to start up a new process entity, you run an executable with command line arguments. This can be done via. GUI menus, but still this is what’s going on. In Squeak you run something by passing a message to a class that instantiates one or more new objects. This is typically done via. icons and menus, but at heart this is what’s going on.

Anyway, back to my dilemma. I was looking to see if there was a way to easily fix this situation, since I considered this behavior to be a bug. I didn’t like that it did this without warning. It turned out to be more complicated than I thought. I realized that it would take a heuristic analyzer to determine that what I was doing was dangerous.

I did a little research, using Google to search the Squeak developers list, looking up the keywords “Squeak ‘idiot proof'”, and interestingly, the first entry that came up was from 1998 where Paul Fernhout had done something very similar. He asked, “Shouldn’t we prevent this?” Here’s what he did:

Dictionary become: nil

Dictionary is, again, a class. become: is a message handled by ProtoObject, the root class of every class in the system. In this case it makes every variable in the entire system that used to point to Dictionary point to nil. The method description also says, “and vice versa”, which I take to mean that every variable in the system that pointed to the argument in become: would point to Dictionary (to use the example). I’m guessing that nil is a special case, but I don’t know.

Anyway, this caused Squeak to crash. The consensus that ensued was that this was okay. Squeak was designed to be a fully modifiable system. In fact, Alan Kay has often said that he wishes that people would take Squeak and use it to create a better system than itself. “Obsolete the darn thing,” he says. The argument on the developers list was if it was made crash-proof, anticipating every possible way it could crash, it would become less of what it was intended to be. Someone feared that, “if you make it idiot proof, then only idiots will use it.” The conclusion seemed to be that Squeak programmers should just follow “the doctor’s rule”: The patient says, “It hurts when I do this.” The doctor says, “Well, don’t do that.”

I can see that this argument has validity, but in this particular instance, I don’t like this explanation. It seems to me that this is an area where some error checking could be easily implemented. Isn’t it erroneous to put nil in for become:? Maybe the answer is no. I at least have an excuse, since I was using the := operator, which is a primitive, and it’s much harder to check for this sort of thing in that context.

I also realized that the reason that code browsers can warn you about doing such things easily is they have menu options for doing things like deleting a class, and they throw up a warning if you try to do that. The browser can clearly make out what you’re trying to do, and check if there are dependencies on what you’re deleting. Checking for “Duration := nil” would be akin to a virus scanner looking for suspicious behavior. I don’t believe even a browser would pick up on this piece of code.

This example drove home the point for me that Squeak is like an operating system, and I as a developer am logged in as root–I can do anything, which means I can royally screw the system up (the image) if I don’t know what I’m doing.

I do have a way out of a mess, though, with Squeak. Fortunately, since it’s image-based, if I had managed to save a screwed-up image, I could just substitute a working image. It’s a good idea to keep a backup “clean” image around for such occasions, that you can just make a copy of. I wouldn’t need to reinstall the OS (to use the analogy). It’s like what people who use virtualization software do to manage different operating systems. They save disk images of their sessions. If one becomes screwed up or infected with a virus, they can just substitute a good one and delete the bad one. Problem solved.

For the most part, I wouldn’t lose any source code either, because that’s all saved in changesets, which I could recover (though Workspaces are only saved if you explicitly save them).

Another thing I could’ve done is opened up another instance of Squeak on a good image, filed out the Duration class (have Squeak serialize the class definition to a text file), and then filed it in (deserialized it), in the corrupted image. I imagine that would’ve solved the problem in my case.

Having said all this, I don’t mean to say that if you’re a Squeak user, working at a more abstract level, say with eToys, that you’re likely to experience a crash in the system. That level of use is pretty stable. Individual apps. may crash, and people have complained about apps. getting messed up in the newer versions, but the system will stay up.

I can understand why some like Ruby. You get access to Smalltalk-like language features, without having “root” access, and thereby the ability to mess things up in the runtime environment. The core runtime is written in C, which conveys a “None but the brave enter here” message. It’s compatible with the file-based paradigm that most developers are familiar with. From what I hear, with the way programming teams are staffed these days at large firms, a technology like Squeak in unskilled hands would probably lead to problems. It’s like the saying in Spiderman: “With power comes responsibility.” Squeak gives the programmer a lot of power, and some power to mess things up. Interestingly, in the 1998 discussion I link to, there was a distinction made between “shooting yourself in the foot” in Smalltalk vs. doing the same in a language like C. The commenter said that a C programmer has to be much more careful than a Squeak programmer does, because a) pointers in C are dangerous, and b) you can’t avoid using them. Whereas in Squeak you don’t have to use facilities that are dangerous to get something useful done. In fact, if you do screw up, Squeak offers several ways you can recover.

In closing, I’ll say that just as a seasoned Unix administrator would never say “rm -r *” from the root directory (though Unix would allow such a command to be executed, destructive as it is), people learning Squeak come to the realization that they have the full power of the system in their hands, and it behooves them to use it with discipline. I know that in a Unix shell you can set up an alias for rm that says “rm -i” that forces a warning. I suppose such an option could be built into Squeak if there was the desire for that. It would depend a lot on context, and Squeak doesn’t really embody that concept at this point.

Squeak is like an operating system

Squeak desktop

The Squeak 3.9 desktop

In foreground is a System Browser (what I call a “code browser”–the default developer IDE), and one of the desktop “flaps” on the right (like a “quick launch” bar–it retracts). Behind the System Browser is the Monticello Browser, a version control system for Squeak. The bar at the top contains some system menus and desktop controls. The wallpaper is called “Altitude”.

Smalltalk is misunderstood. It’s often criticized as one big lock-in platform (like Microsoft Windows, I guess), or as I saw someone say, a “walled garden”, or more often a language that’s “in its own little world.” I think all of these interpretations come about because of this misunderstanding: people think Smalltalk is just a language running on a VM. Period. They don’t understand why it has its own development tools, and its own way of interacting. That doesn’t seem like a typical language to them, but they can’t get past this notion. The truth is Smalltalk is unlike anything most programmers have ever seen before. It doesn’t seem to fit most of the conventions that programmers are trained to see in a language, or a system.

We’re trained that all an operating system represents to a user or a programmer is a manager of resources, and an interaction environment. Programs are stored inactive on disk, along with our data files. We learn that we initiate our programs by starting them from a command line, or clicking on an icon or menu item, through the interaction environment of the OS. When a program is run, it is linked into the system via. a loader, assigned an area of memory, and given access to certain OS resources. Programs are only loaded into memory when they’re running, or put into a state of stasis for later activation.

We’re trained that a “virtual machine,” in the .Net or JVM sense, is a runtime that executes bytecodes and manages its own garbage collected memory environment, and is strictly there to run programs. It may manage its own threads, or not. It becomes active when it’s running programs, and becomes inactive when we shut those programs down. It’s a bit like a primitive OS without its own user interaction model. It remains hidden to most people. We’re trained that programming languages are compilers or interpreters that run on top of the OS. Each is a separate piece: the OS, the development tools, and the software we run. They are linked together only occasionally, and only so long as a tool or a piece of software is in use. Smalltalk runs against the grain of most of this conventional thinking.

Like its predecessor, Smalltalk-80, Squeak functions like an operating system (in Smalltalk-80’s case, it really was an OS, running on the Xerox Alto a Xerox computer). The reason I say “like” an OS, is while it implements many of the basic features we expect from an OS, it doesn’t do everything. In its current implementation it does not become the OS of your computer, nor do any of the other Smalltalk implementations. It doesn’t have its own file system, nor does it natively handle devices. It needs an underlying OS. What distinguishes it from runtimes, like .Net and the JVM, is it has its own GUI–its own user interaction environment (which can be turned off). It has its own development tools, which run inside this interaction environment. It multitasks its own processes. It allows the user to interactively monitor and control background threads through the Process Monitor that also runs inside the environment. Like Lisp’s runtime environment, everything is late-bound, unlike .Net and the JVM. Everything is more integrated together: the kernel, the Smalltalk compiler, the UI, the development tools, and applications. All are implemented as objects running in one environment.

Creating a unified language/OS system was intentional. Alan Kay, the designer of the Smalltalk language, was in a discussion recently on operating systems on the Squeak developers list. He said that an operating system is just the part that’s not included in a programming language. In his opinion, a language should be an integral part of what we call an OS. His rationale was that in order for a program to run, it needs the facilities of the OS. The OS governs I/O, and it governs memory management. What’s the point in keeping a language separate from these facilities if programs are always going to need these things, and would be utterly useless without them? (Update 12-14-2010: Just a note of clarification about this paragraph. Though Alan Kay’s utterance of this idea was the first I’d heard of it, I’ve since seen quotes from Dan Ingalls (the implementor of Smalltalk), from material written a few decades ago, which suggest that the idea should be attributed to him. To be honest I’m not real sure who came up with it first.)

Another reason that there’s misunderstanding about Smalltalk is people think that the Smalltalk language is trying to be the “one language to rule them all” in the Squeak/Smalltalk environment. This is not true.  If you take a look at other systems, like Unix/Linux, Windows, or Mac OS, most of the code base for them was written in C. In some OSes, some of the code is probably even written in assembly language. What are the C/C++ compilers, the Java and .Net runtimes, and Python and Ruby written in? They’re all written in C. Why? Is C trying to be the “one language to rule them all” on those systems? No, but why are they all written in the same language? Why aren’t they written in a variety of languages like Pascal, Lisp, or Scheme? I think any of them would be capable of handling the task of translating source code into machine code, or creating an interpreter. Sure, performance is part of the reason. The main one, though, is that all of the operating systems are fundamentally oriented around the way C does things. The libraries that come with the OS, or with the development systems, are written in it. Most of the kernel is probably written in it. Pascal, assuming it was not written in C, could probably handle dealing with the OS, but it would have a rough time, due to the different calling conventions that are used between it and C. Could Lisp, assuming its runtime wasn’t written in C, either, interact with the OS with no help from C? I doubt it, not unless the OS libraries allowed some kind of universal message passing scheme that it could adapt to.

A major reason Smalltalk seems to be its “own little world” is like any OS, it needs a large variety of tools, applications, and supporting technologies to feel useful to most users, and Smalltalk doesn’t have that right now. It does have its own way of doing things, but nothing says it can’t be changed. As an example, before Monticello came along, versioning used to only take place in the changesets, or via. filing out classes to text files, and then saving them in a version control system.

Saying Smalltalk is isolating is equivalent to saying that BeOS is a “walled garden,” and I’m sure it would feel that way to most. Is any OS any less a “walled garden”? It may not seem like it, but try taking a Windows application and run it on a Mac or Linux without an emulator, or vice versa. You’ll see what I mean. It’s just a question of is the walled garden so big it doesn’t feel confining?

Having said this, Squeak does offer some opportunities for interoperating with the “outside world.” Squeak can open sockets, so it can communicate via. network protocols with other servers and databases. There’s a web service library so it can communicate in SOAP. Other commercial implementations have these features as well. Squeak also has FFI (Foreign Functionality Interface), and OSProcess libraries, which enables Squeak programmers to initiate processes that run on the underlying OS. As I mentioned a while ago, someone ported the wxWidgets library to it, called wxSqueak, so people can write GUI apps. that run on the underlying OS. There’s also Squeak/.Net Bridge, which allows interaction with the .Net runtime, in a late-bound way (though .Net makes you work harder to get what you want in this mode). So, Squeak at least is not an island in principle. Its system support could be better. Other languages like Ruby have more developed OS interoperability libraries at this point.

The “C/C++ effect” you see on most other systems is the equivalent of what you see in Squeak. The Smalltalk language is the “C” of the system. The reason most software out there, even open source, can’t run on it, is at a fundamental level, they’re all written in C or C++. The system languages are so different. Smalltalk also represents a very different system model.

What Smalltalk, and especially Squeak, has achieved that no other system has achieved to date, with the exception of the Lisp machines of old, is a symbolic virtual machine environment that is more relevant to its own use than any other runtime environment out there. In .Net and the JVM, you just use their runtimes to run programs. They’re rather like the old operating systems at the beginning of computing, which were glorified program loaders, though they have some sophisticated technical features the old OSes didn’t have. With Squeak, you’re not just running software on it, you’re using the VM as well, interacting with it. Squeak can be stripped down to the point that it is just a runtime for running programs. There are a few Squeak developers who have done that.

In Smalltalk, rather than machine code and C being software’s primary method of interacting with the machine, bytecode and the Smalltalk language are the basic technologies you work with. This doesn’t mean at all that more languages couldn’t be written to run in the Smalltalk environment. I have no doubt that Ruby or Python could be written in Smalltalk, and used inside the environment, with their syntax and libraries intact. The way in which they’d be run (initiated) would be different, but at heart they would be the same as they are now.

Both Apple and Microsoft are moving towards the Smalltalk model, with the Cocoa development environment on the Mac, and .Net/WPF on Windows. Both have you write software that can run in a bytecode-executing runtime, though the OS is still written in large part in compiled-to-binary code. If desktop OSes have a future, I think we’ll see them move more and more to this model. Even so, there remain a couple of major differences between these approaches: Smalltalk uses a late-binding model for everything it does, so it doesn’t have to be shut off every time you want to change what’s running inside it. Even programs that are executing in it don’t have to be stopped. .Net uses an early-binding model, though it emulates late binding pretty well in ASP.Net now. I can’t comment on Cocoa and Objective C, since I haven’t used them. Another difference is, like Linux, Squeak is completely open source. So everything is modifiable, right down to the kernel. As I’ll get into in my next post, this is a double-edged sword.

Update 7/20/07: I found this in the reddit comments to this blog post. Apparently, there is a version of Squeak that IS an operating system, called SqueakNOS, that allows you to boot your computer into Squeak, as if it was an OS. The name stands for “Squeak No Operating System” (underneath it). It comes in an ISO image that you can burn to CD. From the screenshot, it shows that it has a concept of devices, displaying tabs for the CD-ROM drive, serial port, and NIC.

I think I had heard the name of SqueakNOS before this, but I didn’t know what it was. The version of Squeak that most people have is the kind that rides on top of an existing OS, not this, but it’s nice to know that this is out there. Personally, I like the kind I have, since it allows me to do what I like doing in Squeak, and if I want resources it doesn’t have available, then I can go to the OS I’m running. I used to hear about a version of Linux that ran this way, so people didn’t have to dual boot, or use virtualization software. There’s no “dishonor” in it.

One person in the reddit comments said they wished it had a “good web browser that supported AJAX.” Me too. There is a HTML browser called “Scamper”, available from SqueakMap. It used to be included in the image, but in the latest version from it looks like it’s been taken out. It seems that lately, Squeak developers have preferred the idea of having Squeak control the default browser on your system (IE, Safari, Firefox, etc.) to using a browser internal to Squeak. The last I saw Scamper, it was a bare-bones HTML browser that just displayed text in a standard system font. It could be better.

Update 1/18/20: I happened to research SqueakNOS last year for a bit, and found out it didn’t technically run as the computer’s operating system. It just acted like one. What actually happened is the computer booted into a stripped down version of Linux, which automatically ran Squeak as its sole application at boot up. This is how Chromebooks operate. My guess is the device management in SqueakNOS manipulated drivers in Linux.

Redefining computing, Part 2

“Pascal is for building pyramids–imposing, breathtaking, static structures built by armies pushing heavy blocks into place. Lisp is for building organisms–imposing, breathtaking, dynamic structures built by squads fitting fluctuating myriads of simpler organisms into place.”

— from forward written by Alan Perlis for
Structure and Interpretation of Computer Programs

In this post I’m going to talk mostly about a keynote speech Alan Kay gave at the 1997 OOPSLA conference, called “The Computer Revolution Hasn’t Happened Yet,” how he relates computing to biological systems, and his argument that software systems, particularly OOP, should emulate biological systems. In part 1 I talked a bit about Peter Denning’s declaration that “Computing is a Natural Science”.

Please note: There is a bit of mature language in this speech. It’s one sentence. If you are easily offended, errm…plug your ears, avert your eyes, whatever. It’s where he’s talking about Dr. Dijkstra.

This speech reminds me that when I started hearing about gene therapies being used to treat disease, I got the idea that this was a form of programming–reprogramming cells to operate differently, using the “machine code” of the cell: DNA.

While scientists are discovering that there’s computation going on around us in places we did not suspect, Kay was, and still is, trying to get us developers to make our software “alive,” capable of handling change and growth–to scale–without being disturbed to a significant degree. That’s what his conception of OOP was based on to begin with. A key part of this is a late-bound system which allows changes to be made dynamically. Kay makes the point as well that the internet is like this, though he only had a tiny hand in it.

One of the most striking things to me he’s touched on in this speech, which he’s given several times, though it’s a bit different each time, is that computing introduces a new kind of math, a finite mathematics that he says is more practical and more closely resembles things that are real, as opposed to the non-bounded quality of classical mathematics, which often does not. Maybe I’m wrong, but it seems to me from what he says, he sees this finite math as better than classical math at describing the world around us. As noted in my previous post, Peter Denning says in his article “Computing is a Natural Science”:

Stephen Wolfram proclaimed [in his book A New Kind of Science] that nature is written in the language of computation, challenging Galileo’s claim that it is written in mathematics.

So what’s going on here? It definitely sounds like CS and the other sciences are merging some. I learned certain finite math disciplines in high school and college, which related to my study of computer science. I never expected them to be substitutes for classical math in the sciences. If someone can fill me in on this I’d be interested to hear more. I don’t know, but this memory just flashed through my head; that scene in “Xanadu” where a band from the 40s, and a band from the 80s merge together into one performance. They’re singing different songs, but they mesh. Crazy what one’s mind can come up with, huh. 🙂 I know, I know. “Xanadu” was a cheesy movie, but this scene was one of the better ones in it, if you can tolerate the fashions.

I think this speech has caused me to look at OOP in a new way. When I was first training myself in OOP years ago, I went through the same lesson plan I’m sure a lot of you did, which was “Let’s make a class called ‘Mammal’. Okay, now let’s create a derived class off of that called ‘Canine’, and derive ‘Dog’ and ‘Wolf’ off of that,” or, “Let’s create a ‘Shape’ class. Now derive ‘Triangle’ and ‘Ellipse’ off of that, and then derive ‘Circle’ from ‘Ellipse’.” What these exercises were really doing was teaching the structure and techniques of OOP, and showing some of their practical advantages, but none of it taught you why you were doing it. Kay’s presentation gave me the “why”, and he makes a pretty good case that OOP is not merely a neat new way to program, but is in fact essential for developing complex systems, or at least the best model discovered so far for doing it. He also points out that the way OOP is implemented today is missing one critical element–dynamism, due to the early-bound languages/systems we’re using, and that a lot of us have misunderstood what he intended OOP to be about.

Alan Kay relates the metaphor of biological systems to software systems, from his speech at the 1997 OOPSLA conference

If you don’t want to listen to the whole speech, I’ve printed some excerpts from it below, only including the parts that fit the biological metaphor he was getting across. I’ve included my own annotations in []’s, and commentary in between excerpts. I’ve also included some links.

Dr. Kay gets into this discussion, using a spat he and Dr. Dijkstra got into some years before over who were the better computer scientists, the Europeans or the Americans, as a launching point. Dijkstra made the point that European computer scientists had more of a math background than Americans did, and they got their positions by working harder at it than Americans, etc. Kay responded with, “Huh, so why do we write most of the software, then?” (I’m paraphrasing). He continues:

Computers form a new kind of math. They don’t really fit well into classical math. And people who try to do that are basically indulging in a form of masturbation…maybe even realizing it. It was a kind of a practical math. The balance was between making structures that were supposed to be consistent of a much larger kind than classical math had ever come close to dreaming of attempting, and having to deal with [the] exact same problems that classical math of any size has to deal with, which is being able to be convincing about having covered all of the cases.

There’s a mathematician by the name of Euler [pronouned “Oiler”] whose speculations about what might be true formed 20 large books, and most of them were true. Most of them were right. Almost all of his proofs were wrong. And many PhDs in mathematics in the last and this century have been formed by mathematicians going to Euler’s books, finding one of his proofs, showing it was a bad proof, and then guessing that his insight was probably correct and finding a much more convincing proof. And so debugging actually goes on in mathematics as well.

And I think the main thing about doing OOP work, or any kind of programming work, is that there has to be some exquisite blend between beauty and practicality. There’s no reason to sacrifice either one of those, and people who are willing to sacrifice either one of those I don’t think really get what computing is all about. It’s like saying I have really great ideas for paintings, but I’m just going to use a brush, but no paint. You know, so my ideas will be represented by the gestures I make over the paper; and don’t tell any 20th century artists that, or they might decide to make a videotape of them doing that and put it in a museum. . . .

Kay used a concept, called bisociation, from a book called The Act of Creation”, by Arthur Koestler. Koestler draws out a “pink plane” with a trail of ants on it, which represents one paradigm, one train of thought, that starts out with an idea and works towards continuous improvement upon it. Kay said about it:

If you think about that, it means that progress in a fixed context is almost always a form of optimization, because if you were actually coming up with something new it wouldn’t have been part of the rules or the context for what the pink plane is all about. So creative acts generally are ones that don’t stay in the same context that they’re in. So he says every once in a while, even though you have been taught carefully by parents and by school for many years, you have a “blue” idea.

This introduces a new context.

[Koestler] also pointed out that you have to have something “blue” to have “blue” thoughts with, and I think this is something that is generally missed in people who specialize to the extent of anything else. When you specialize you’re basically putting yourself into a mental state where optimization is pretty much all you can do. You have to learn lots of different kinds of things in order to have the start of these other contexts.

This is the reason he says a general education is important. Next, he gets into the biological metaphor for computing:

One of my undergraduate majors was in molecular biology, and my particular interest was both in cell physiology and in embryology–morphogenesis they call it today. And this book, The Molecular Biology of the Gene had just come out in 1965, and–wonderful book, still in print, and of course it’s gone through many, many editions, and probably the only words that are common between this book and the one of today are the articles, like “the” and “and”. Actually the word “gene” I think is still in there, but it means something completely different now. But one of the things that Watson did in this book is to make an assay–first assay of an entire living creature, and that was the E. Coli bacterium. So if you look inside one of these, the complexity is staggering.

He brings up the slide of an E. Coli bacterium as seen through an (electron?) microscope.

Those “popcorn” things are protein molecules that have about 5,000 atoms in them, and as you can see on the slide, when you get rid of the small molecules like water, and calcium ions, and potassium ions, and so forth, which constitute about 70% of the mass of this thing, the 30% that remains has about 120 million components that interact with each other in an informational way, and each one of these components carries quite a bit of information [my emphasis]. The simple-minded way of thinking of these things is it works kind of like OPS5 [OPS5 is an AI language that uses a set of condition-action rules to represent knowledge. It was developed in the late 1970s]. There’s a pattern matcher, and then there are things that happen if patterns are matched successfully. So the state that’s involved in that is about 100 Gigs., and you can multiply that out today. It’s only 100 desktops, or so [it would be 1/2-1/3 of a desktop today], but it’s still pretty impressive as [an] amount of computation, and maybe the most interesting thing about this structure is that the rapidity of computation seriously rivals that of computers today, particularly when you’re considering it’s done in parallel. For example, one of those popcorn-sized things moves its own length in just 2 nanoseconds. So one way of visualizing that is if an atom was the size of a tennis ball, then one of these protein molecules would be about the size of a Volkswagon, and it’s moving its own length in 2 nanoseconds. That’s about 8 feet on our scale of things. And can anybody do the arithmetic to tell me what fraction of the speed of light moving 8 feet in 2 nanoseconds is?…[there’s a response from the audience] Four times! Yeah. Four times the speed of light [he moves his arm up]–scale. So if you ever wondered why chemistry works, this is why. The thermal agitation down there is so unbelievably violent, that we could not imagine it, even with the aid of computers. There’s nothing to be seen inside one of these things until you kill it, because it is just a complete blur of activity, and under good conditions it only takes about 15 to 18 minutes for one of these to completely duplicate itself. Okay. So that’s a bacterium. And of course, lots more is known today.

Another fact to relate this to us, is that these bacteria are about 1/500th the size of the cells in our bodies, which instead of 120 million informational components, have about 60 billion, and we have between 1012, maybe 1013, maybe even more of these cells in our body. And yet only 50 cell divisions happen in a 9-month pregnancy. It only takes 50 cell divisions to make a baby. And actually if you multiply it out, you realize you only need around 40. And the extra 10 powers of 10 are there because during the embryological process, many of the cells that are not fit in one way or another for the organism as a whole are killed. So things are done by over-proliferating, testing, and trimming to this much larger plan. And then of course, each one of these structures, us, is embedded in an enormous biomass.

So to a person whose “blue” context might have been biology, something like a computer could not possibly be regarded as particularly complex, or large, or fast. Slow. Small. Stupid. That’s what computers are. So the question is how can we get them to realize their destiny?

So the shift in point of view here is from–There’s this problem, if you take things like doghouses, they don’t scale [in size] by a factor of 100 very well. If you take things like clocks, they don’t scale by a factor of 100 very well. Take things like cells, they not only scale by factors of 100, but by factors of a trillion. And the question is how do they do it, and how might we adapt this idea for building complex systems?

He brings up a slide of a basic biological cell. He uses the metaphor of the cell to talk about OOP, as he conceived it, and building software systems:

Okay, this is the simple one. This is the one by the way that C++ has still not figured out, though. There’s no idea so simple and powerful that you can’t get zillions of people to misunderstand it. So you must, must, must not allow the interior of any one of these things to be a factor in the computation of the whole, okay. And this is only part of this story. It’s not just the cell–the cell membrane is there to keep most things out, as much as it is there to keep certain things in.

And a lot of, I think, our confusion with objects is the problem that in our Western culture, we have a language that has very hard nouns and verbs in it. So our process words stink. So it’s much easier for us when we think of an object–I have apologized profusely over the last 20 years for making up the term “object-oriented”, because as soon as it started to be misapplied, I realized that I should’ve used a much more process-oriented term for it. Now, the Japanese have an interesting word, which is called “ma”, which spelled in English is M-A, “ma”. And “ma” is the stuff in between what we call objects. It’s the stuff we don’t see, because we’re focused on the noun-ness of things, rather than the process-ness of things, whereas Japanese has a more process/feel-oriented way of looking at how things relate to each other. You can always tell that by looking at the size of a word it takes to express something that is important. So “ma” is very short. We have to use words like “interstitial”, or worse, to approximate what the Japanese are talking about.

I’ve seen him use this analogy of the Japanese word “ma” before in more recent versions of this speech. What he kind of beats around the bush about here is that the objects themselves are not nearly as important as the messages that are sent between them. This is the “ma” he’s talking about–what is going on between the objects, their relationships to each other. To me, he’s also emphasizing architecture here. In a different version of this speech (I believe), he said that the true abstraction in OOP is in the messaging that goes on between objects, not the objects themselves.

He continues:

So, the realization here–and it’s not possible to assign this realization to any particular person, because it was in the seeds of Sketchpad, and in the seeds of the Air Training Command file system, and in the seeds of Simula–and that is, that once you have encapsulated in such a way that there is an interface between the inside and the outside, it is possible to make an object act like anything, and the reason is simply this: that what you have encapsulated is a computer [my emphasis]. So you have done a powerful thing in computer science, which is to take the powerful thing you’re working on and not lose it by partitioning up your design space. This is the bug in data procedures–data and procedure languages. And I think this is the most pernicious thing about languages like C++ and Java, [which] is they think they are helping the programmer by looking as much like the old thing as possible, but in fact they’re hurting the programmer terribly, by making it difficult for the programmer to understand what’s really powerful about this new metaphor.

The “Air Training Command file system” refers to a way that data was stored on tapes back when Kay was in the Air Force, I think in the 1950s in the early 1960s. It was effective and efficient. Some have pointed to it as the first example Kay had seen of an object-oriented system. The first section of tape contained pointers to routines (probably hard addresses to memory locations, in those days) whose code was stored in a second section of the tape, which read/manipulated the data on the third section of the tape. This way, it didn’t matter what format the data came in, since that was abstracted by the routines in the second section. No one knows who came up with the scheme.

And again, people who were doing time-sharing systems had already figured this out as well. Butler Lampson’s thesis in 1965 was about–that what you want to give a person on a time-sharing system is something that is now called a virtual machine, which is not the same as what the Java VM is, but something that is as much like the physical computer as possible, but give one separately to everybody. Unix had that sense about it, and the biggest problem with that scheme is that a Unix process had an overhead of about 2,000 bytes just to have a process. And so it’s going to be difficult in Unix to let a Unix process just be the number 3. So you’d be going from 3 bits to a couple of thousand bytes, and you have this problem with scaling.

So a lot of the problem here is both deciding that the biological metaphor [my emphasis] is the one that is going to win out over the next 25 years or so, and then committing to it enough to get it so it can be practical at all of the levels of scale that we actually need. Then we have one trick we can do that biology doesn’t know how to do, which is we can take the DNA out of the cells, and that allows us to deal with cystic fibrosis much more easily than the way it’s done today. And systems do have cystic fibrosis, and some of you may know that cystic fibrosis today for some people is treated by infecting them with a virus, a modified cold virus, giving them a lung infection, but the defective gene for cystic fibrosis is in this cold virus, and the cold virus is too weak to actually destroy the lungs like pneumonia does, but it is strong enough to insert a copy of that gene in every cell in the lungs. And that is what does the trick. That’s a very complicated way of reprogramming an organism’s DNA once it has gotten started.

He really mixes metaphors here, going from “cystic fibrosis” in computing, to it in a biological system. I got confused on what he said about the gene therapy. Perhaps he meant that the virus carries the “non-defective gene”? I thought what the therapy did was substitute a good gene for the bad one, since cystic fibrosis is a genetic condition, but then, I don’t really know how this works.

When he talks about “taking the DNA out of the cell,” and dealing with “cystic fibrosis,” I’m pretty sure he’s talking about a quality of dynamic OOP systems (like Smalltalk) that work like Ivan Sutherland’s Sketchpad program from the 1960s, where each object instance was based on a master object. If you modified the master object, that change got reflected automatically in all of the object instances.

He brought up another slide that looks like a matrix (chart) of characteristics of some kind. I couldn’t see it too well. I recognized the subject though. He begins to talk about his conception of the semantic web, using the same biological and object-oriented metaphor:

So here’s one that is amazing to me, that we haven’t seen more of. For instance, one of the most amazing things to me, of people who have been trying to put OOP on the internet, is that I do not–I hope someone will come up afterwards and tell me of an exception to this–but I do not know of anybody yet who has realized that at the very least every object should have a URL, because what the heck are they if they aren’t these things. And I believe that every object on the internet should have an IP, because that represents much better what the actual abstractions are of physical hardware to the bits. So this is an early insight, that objects basically are like servers. And this notion of polymorphism, which used to be called generic procedures, is a way of thinking about classes of these servers. Everybody knows about that.

He brought up another slide, showing the picture of a building crane on one side, and a collection of biological cells on the other. More metaphors.

And here’s one that we haven’t really faced up to much yet, that now we’ll have to construct this stuff, and soon we’ll be required to grow it. So it’s very easy, for instance, to grow a baby 6 inches. They do it about 10 times in their life. You never have to take it down for maintenance. But if you try and grow a 747, you’re faced with an unbelievable problem, because it’s in this simple-minded mechanical world in which the only object has been to make the artifact in the first place, not to fix it, not to change it, not to let it live for 100 years.

So let me ask a question. I won’t take names, but how many people here still use a language that essentially forces you–the development system forces you to develop outside of the language [perhaps he means “outside the VM environment”?], compile and reload, and go, even if it’s fast, like Virtual Cafe (sic). How many here still do that? Let’s just see. Come on. Admit it. We can have a Texas tent meeting later. Yeah, so if you think about that, that cannot possibly be other than a dead end for building complex systems, where much of the building of complex systems is in part going to go to trying to understand what the possibilities for interoperability is with things that already exist.

Now, I just played a very minor part in the design of the ARPANet. I was one of 30 graduate students who went to systems design meetings to try and formulate design principles for the ARPANet, also about 30 years ago, and if you think about–the ARPANet of course became the internet–and from the time it started running, which is around 1969 or so, to this day, it has expanded by a factor of about 100 million. So that’s pretty good. Eight orders or magnitude. And as far as anybody can tell–I talked to Larry Roberts about this the other day–there’s not one physical atom in the internet today that was in the original ARPANet, and there is not one line of code in the internet today that was in the original ARPANet. Of course if we’d had IBM mainframes in the orignal ARPANet that wouldn’t have been true. So this is a system that has expanded by 100 million, and has changed every atom and every bit, and has never had to stop! That is the metaphor we absolutely must apply to what we think are smaller things. When we think programming is small, that’s why your programs are so big! . . .

There are going to be dozens and dozens–there almost already are–dozens and dozens of different object systems, all with very similar semantics, but with very different pragmatic details. And if you think of what a URL actually is, and if you think of what an HTTP message actually is, and if you think of what an object actually is, and if you think of what an object-oriented pointer actually is, I think it should be pretty clear that any object-oriented language can internalize its own local pointers to any object in the world, regardless of where it was made. That’s the whole point of not being able to see inside. And so a semantic interoperability is possible almost immediately by simply taking that stance. So this is going to change, really, everything. And things like Java Beans and CORBA are not going to suffice, because at some point one is going to have to start really discovering what objects think they can do. And this is going to lead to a universal interface language, which is not a programming language, per se. It’s more like a prototyping language that allows an interchange of deep information about what objects think they can do. It allows objects to make experiments with other objects in a safe way to see how they respond to various messages. This is going to be a critical thing to automate in the next 10 years. . . .

I think what he meant by “any object-oriented language can internalize its own local pointers to any object in the world, regardless of where it was made” is that any OOP language can abstract its pointers so that there’s no distinction between pointers to local objects and URLs to remote objects. This would make dealing with local and remote objects seamless, assuming you’re using a late-bound, message-passing metaphor throughout your system. The seamlessness would not be perfect in an early-bound system, because the compiler would ensure that all classes for which there are messages existed before runtime, but there’s no way to insure that every object on the internet is always going to be available, and always at the same URL/address.

You might ask, “Why would you want that kind of ‘perfect’ seamlessness? Don’t you want that insurance of knowing that everything connects up the way it should?” My answer is, things change. One of the things Kay is arguing here is that our software needs to be adaptable to change, both in itself, and in the “outside world” of the internet. He uses the internet as an example of a system that has been very robust in the face of change. Early-bound systems have a tendency to push the programmer towards assuming that everything will connect up just as it is today, and that nothing will change.

As I heard him talk about objects on the web, the first thing that came to mind was REST (the whole “each object should have a URL” idea). It seems like the first try at an implementation of this idea of objects “experimenting” and “figuring out” what other objects on the network can do was started with the idea of WSDL and UDDI, but that flopped, from what I hear. Microsoft has made a bit of a start with this, in my opinion, with WCF, but it only determines what type of object is at the other end, as in “Is it DCOM?”, “Is it an XML web service?”, etc. It frees the programmer from having to do that. It still allows the client program to interogate the object, but it’s not going to do “experiments” on it for you. It may allow the client program to do them more easily than before. I don’t know.

Kay ends with a note of encouragement:

Look for the “blue” thoughts. And I was trying to think of a way–how could I stop this talk, because I’ll go on and on, and I remembered a story. I’m a pipe organist. Most pipe organists have a hero whose name was E. Power Biggs. He kind of revived the interest in the pipe organ, especially as it was played in the 17th and 18th centuries, and had a tremendous influence on all of us organists.  And a good friend of mine was E. Power Biggs’s assistant for many years, back in the 40s and 50s. He’s in his 80s now. When we get him for dinner, we always get him to tell E. Power Biggs stories. The organ that E. Power Biggs had in those days for his broadcasts was a dinky little organ, neither fish nor foul, in a small museum at Harvard, called the Busch-Reisinger Museum; but in fact all manner of music was played on it. And one day this assistant had to fill in for Biggs, and he asked Biggs, “What is the piece [to be] played?” And he said, “Well I had programmed Cesar Frank’s heroic piece”. And if you know this piece it is made for the largest organs that have ever been made, the loudest organs that have ever been made, in the largest cathedrals that have ever been made, because it’s a 19th century symphonic type organ work. And Biggs was asking my friend to play this on this dinky little organ, and he said, “How can I play it on this?”, and Biggsy said, “Just play it grand! Just play it grand!” And the way to stay with the future as it moves, is to always play your systems more grand than they seem to be right now. Thank you.

Redefining computing, Part 1

Is everything a form of computation? That’s what some scientists are saying. I found the CACM article “Computing is a Natural Science”, by Peter Denning on reddit recently. I looked at the title and thought, “Yeah, so?” When I took computer science at Colorado State University 14 years ago it was in the College of Natural Sciences. At some universities it was in the College of Engineering. I don’t think it got to where it was at my school because the faculty was being extraordinarily perceptive. I don’t remember my teachers talking about this concept that natural processes are being “computed”. Mathematics was in the Natural Sciences college as well. Computer science is historically an offshoot of mathematics. So it follows that it would be in the same college.

Anyway, at first glance I thought the article was trying to make a provocative argument that CS should be in the Natural Sciences college…and perhaps it should. The article is deeper than it appeared. Mark Guzdial gave a good analysis of it (Update 5-24-2013: the blog where he wrote this has disappeared), so I won’t repeat it here. This quote from it is a good summary:

Peter [Denning] makes the point that scientists are discovering that much of nature is about information processing. Books like Stephen Wolfram’s A New Kind of Science make the point that algorithms underlie much of nature–“nature is written in the language of computation, challenging Galileo’s claim that it is written in mathematics.” Thus, studying computing is studying nature. I highly recommend the article. I particularly like his conclusion where he points out, “Computing is no longer a science of just the artificial [my emphasis]. It is the study of information processes, natural and artificial.”

It dovetails into something he’s been talking about for a while, that CS is branching out and being adopted by other disciplines, such as the sciences. For example, programming is being taught in physics classes at some universities now. Students are expected to write programs related to the material as part of the course.

The CACM article reminds me of one I heard about in Scientific American a while back. Someone published a theory a few years ago saying that the universe is actually a holographic computer (just linking to this for the summary). (Edit 1/23/20: I can no longer find the article to which I was referring.)

In the next part I’ll discuss a speech that Alan Kay gave 10 years ago where he makes the same points in regards to molecular biology. I’m speculating, but it’s not too difficult to believe that Kay figured out there is computation going on inside of biological cells more than 30 years ago when he developed OOP and Smalltalk, perhaps before then. As he conceived it, OOP uses biological metaphores.

I can understand the notion of biological computation. Once you see how Kay explains it, I think it’ll make sense to you as well. I guess this makes sense for the other fields of science if you view computation as just a series of predictable and quantifiable stimuli and responses, where the responses follow discernable rules.

The real computer revolution

For so many years Alan Kay has been saying “The computer revolution hasn’t happened yet”. He sees the computer as a new medium, just as the book and printing press represented a new medium in the Middle Ages. He’s said that we will know when the computer revolution has arrived when we learn to communicate in a way that is only possible with the computer. I can’t find the source for this, but I know he’s said it. I don’t believe he meant things like YouTube, or even blogging, though tagging would probably be a part of it. He meant something more socially transformative. Just as the book and printing press democratized knowledge, and enabled people to discuss ideas with each other using argument and logic, instead of always appealing to authority–creating fertile ground for democratic movements–the computer has the same potential. Most of all, the computer revolution, in his view, is not the “automation of paper”. Remember the “vision of the future” that was once touted as the business computing panacea of the “paperless office”? He says that’s not it.

I tried a little exercise after hearing this. I tried to think what would this unique form of communication be? The only thought that came to mind was simulation, the ability to model a phenomenon or process, and use it to communicate ideas about them. When I thought about whether this was being done already, the first thought that came to my head was the whole issue of global warming and what’s causing it. A lot of the arguments around it are generated off of atmospheric computer models being generated by scientists, though right now it seems to me this process is imperfect. I’m just using it as an example of something that’s starting to happen with respect to computing as a medium, and what it signifies.

I found this blog post recently by Mark Guzdial, called “Computing for Knowledge Transformation” (it’s on his author blog on (Update 5-24-2013: This is from Mark’s Amazon blog that has since disappeared. He created a new blog a few years ago using WordPress, though I don’t believe he moved his old blog posts). He has outlined some more ideas regarding what the true impact of computing will be on the future.

Guzdial has been exploring what computer science education means today, given the current state it’s in. An idea of his that’s been catching on where he works, at Georgia Tech, is Media Computation–applying computer science and programming to media, such as graphics, video, and audio. It’s been attracting a lot of interest. And get this, most a lot quite a few of the students in his class are female! People should take a look at this.

Anyway, he discusses a concept of writing I found interesting: that beginners, writers just starting out, “write to tell,” basically regurgitating knowledge, and experts “transform knowledge” in the process of their writing. The writer synthesizes his/her piece, drawing together varying sources of information, and the writer is transformed in the process, gaining new knowledge. I could relate to this. Just doing a little self reflection I’d say I’ve been doing quite a bit of the former on this blog, and a bit of the latter. He said that the same could be said of computing: there’s “knowledge telling” (he cites PowerPoint as an example of this mode of computing. Quite apt I’d say…), and then there’s “knowledge transformation.”  The future of computing is the latter:

Computational scientists are using computing as a way of creating knowledge, of figuring out how to communicate it, and of a way of transforming their own knowledge in the process.  In fact, all forms of Computational-X (where X is journalism, photography, biology, chemistry, and so on) are about transforming knowledge in X through effective use of computation.

Programming is an important tool when using computing for knowledge transformation.  If you are using the computer as a way of creating new knowledge, you are almost certainly using the computer in a new way that others have not considered.  You cannot do an HCI process of task analysis when the task is “invent a process or representation that has never been created before.”

Note that “effective use” has nothing to do with software engineering.  Most computational science code that I’ve seen is pretty poor engineering quality. (Which does raise the interesting research question of what kind of program methodology and structuring makes the most sense for computational-X professionals and what will they actually use.)

“Computational Thinking” and “Computing for Knowledge Transformation” are both verb-like phrases — it’s what you do.  What do we teachers teach if we want people to learn computational thinking, to achieve computing for knowledge transformation? What computing for knowledge transformation is about includes:

  • Representations: Using computing to understand how information and models in a domain might be structured.
  • Mappings: Between representations, between models and the real world counterparts.
  • Simulation: Execution of a model to test it, to gather data on it, to expore information in silico.
  • Integration: We don’t program in C4KT in order to build an artifact.  We program to explore ideas and create knowledge, where the output will probably be read into Excel and graphed, or will drive a script in Maya to generate an animation. Programming in C4KT is not about programming a blank sheet of paper to create a new killer app.  It’s about creating the data, models, and representations that can’t be created in existing tools, then moving back to the existing tools, perhaps for analysis and visualization.

(my emphasis in bold italics)

I’ve probably cited this before, but as I read this, I can’t help but think of the spreadsheet. It accomplishes some of these tasks for some domains. I think the key is to build on that model of what an application is, to create more opportunities for exploration. At least that’s a way that most people right now can relate to this. Kay would probably argue for the “total computing environment,” where programming and “tangible modeling” (you create models and manipulate them using an intuitive system interface) is emphasized more, and applications hold less sway.

What Guzdial discusses here sounds very scientific. I can imagine scholars and researchers using these sophisticated techniques to advance knowledge, but I’m wondering what about opportunities for this in the business community? What about opportunities for this among average people? Certainly spreadsheets are used by some average computer users. A more popular example might be the use of photo editing software. It typically doesn’t involve programming, but it does delve into the realm of simulation (you can preview what your edit will look like before you finalize it), though it’s a simple form of that. It does at least allow exploration.

I’m not expecting Guzdial to come up with the answer for this (though if he’d like to, I wouldn’t mind hearing about it). This is sort of a train of thought post. I thought Guzdial’s post was very interesting, because it helped answer a question that’s been rattling around in my head ever since Alan Kay talked about this: What will the computer revolution really look like? I think Guzdial is on to the answer.

Having fun playing with fire, er…C

This topic takes me back to some of the “good old days” of when I was a C programmer. I found “Top 10 Ways to be Screwed by the C programming language”, by Dave Dyer, on reddit. As I read through it I got a chuckle. Here were some good ones.

Note: none of the code examples display carriage-returns in strings that are printed. For whatever reason my blog software has a real problem with them.

Accidental assignment/Accidental Booleans

        if(a=b) c; /* a always equals b, but c                       will be executed if b!=0 */

Depending on your viewpoint, the bug in the language is that the assignment operator is too easy to confuse with the equality operator; or maybe the bug is that C doesn’t much care what constitutes a boolean expression: (a=b) is not a boolean expression! (but C doesn’t care).

No, this was not a bug in the language. It’s working the way it was intended. Fundamentally, C has a simple structure. Part of that is you can evaluate expressions just about anywhere, no matter what type they are. It works the same way in for-loops:

int i;
for (printf("Starting processes"), i = 0;
      ExecuteProcess(i) && i < 6;
      printf("Processes executed successfully"), i++); 

In this example, ExecuteProcess() returns 0 for failure or a non-zero value for success. That’s how it determines “true” and “false”. 0 == “false”. The example above will work. It’s hackerish, and it’s something I tried to avoid doing in my own code just to avoid confounding others, but the language designers wanted to allow this. The way they saw it, a for-loop was just a “form” that had an initialization step, a test, a code block that would get executed (if you put one in–the fact that I didn’t is intentional), and a post-execution step. You can pour whatever you want into these slots. The if construct is no different. In this way, C is a bit like Lisp, which has similar “open-ended” forms where you can put any sort of expression into the slots of constructs.

Closely related to this lack of rigor in booleans, consider this construction:

        if( 0 < a < 5) c; /* this "boolean"                              is always true! */

Always true because (0<a) generates either 0 or 1 depending on if (0<a), then compares the result to 5, which is always true, of course. C doesn’t really have boolean expressions, it only pretends to.

I forget when was the last time I’d seen constructs like this that actually worked. Maybe BASIC? It’s useful, but he’s right. It won’t fly in C. The reason is that it looks at r-values (which is what the code inside the if statement is) as an expression to evaluate. Nothing more. It doesn’t consider the context. As such, it evaluates expressions according to some rules. A book I got years ago, called “The C Programming Language”, “C: A Reference Manual”, by Harbison and Steele, is an excellent book on C. There was one page I went to more than any other. It had a hierarchical list of all the operators you could use, and what precedence they had in relation to each other. The higher up in the list, the higher their precedence. Some operators were equal in precedence, in which case they’d just be evaluated from left to right. Dyer’s example above is one such case.

Or consider this:

if( a =! b) c;      /* this is compiled as (a = !b)
                       an assignment, rather than
                       (a != b) or (a == !b) */

Yes, it’s a typo. What do you expect? I understand that in more modern languages, like C# (maybe Java, too), this would’ve been flagged. I know in C#, it flags it if it sees an assignment inside a conditional statement. I forget if it’s just a warning or a syntax error.

Unhygienic macros

        #define assign(a,b)


        x=(char)y>>8    /* probably not what
                           you want */

I didn’t get this example. Yes, you have to be careful how you construct your macros so they fit the situations you intend to use them in. Just common sense, if you ask me. Just rewrite the macro like so: “#define assign(a, b) a=(char)(b)”. So for, “assign(x,y>>8)” you’ll get “x=(char)(y>>8)”. That wasn’t so hard, was it?

Mismatched header files
Suppose foo.h contains:

        struct foo { BOOL a};
file F1.c contains         #define BOOL char
                           #include "foo.h"

file F2.c contains         #define BOOL int
                           #include "foo.h"

now, F1. and F2 disagree about the fundamental attributes of structure “foo”. If they talk to each other, You Lose!

This is just undisciplined coding at work. The place to define a value like BOOL is in something like a types.h file. You would then include that file inside foo.h. This way, whenever you include foo.h, you also get a consistent BOOL type built into the inclusion.

Unpredictable struct construction
Consider this bit packing struct:

    struct eeh_type    {
            uint16 size: 10;  /* 10 bits */
            uint16 code: 6;   /* 6 bits */

Depending on which C compiler, and which “endian” flavor of machine you are on, this might actually be implemented as


or as


Also, again depending on the C compiler, machine architecture, and various mysterious preference settings,the items might be aligned to the nearest 8, 16, 32, or 64 bits. So what matters? If you are trying to match bits with a real world file, everything!

Need another way to lose big? How about this:

Rect foo = {0,1,2,3}; // assign numbers to
                      // the first four slots

You may think you know what those four slots are, but there’s at least an even chance you’ll have to discover the hard way if the structure ever changes.

Indefinite order of evaluation (contributed by Xavier @

        foo(pointer->member, pointer = &buffer[0]);

Works with gcc (and other compilers I used until I tried acc) and does not with acc. The reason is that gcc evaluates function arguments from left to right, while acc evaluates arguments from right to left. K&R and ANSI/ISO C specifications do not define the order of evaluation for function arguments. It can be left-to-right, right-to-left or anything else and is “unspecified”. Thus any code which relies on this order of evaluation is doomed to be non portable, even across compilers on the same platform.

This isn’t an entirely non controversial point of view. Read the supplementary dialog on the subject. [link does not work — Mark]

A fundamental misunderstanding of C I’ve seen occasionally is programmers not recognizing that it’s just a higher level assembly language. This goes for Dyer’s complaint about “fake booleans” as well. If you really want to grok why C does what it does, check out an assembly language sometime.

ANSI C might’ve helped alleviate this misunderstanding some (or maybe it just created more confusion). K&R C was the epitome of the “higher level assembly language” mindset. It’s the original C language, the one that Kernigan & Ritchie wrote (hence the name). It didn’t care about anything except for syntax. It cared nothing for types, even though you had to specify them. All types did for K&R C was tell it how much memory you wanted for a variable, and/or how big of an offset in memory you wanted between it and other variable values. I don’t know for sure, but I think it was the originator of the concept that an index into an array is just an offset into it, not an enumerator for its elements.

For example, back when I used it in college, an int was 16 bits (2 bytes), and it would allocate that on the stack for me, and keep track of its length, if I declared an int variable. That was it. It didn’t care what I put in it, just as an assembler wouldn’t check what type of value I put into a memory location.

If the compiler put adjacent fields in a struct into contiguous memory locations, it would allocate the necessary amount of memory for the struct by adding up the length of each variable specified in it, and then allocate the total amount for it. If I referenced a field within that struct, it was just an offset and a length into that memory area. Again, it didn’t care what type of value I put in it.

I discovered a couple years out of college that one could use this property of structs, even in ANSI C, to parse binary files. To tell you the truth, I think structs and bit fields were made for this sort of thing. Some example file reading code would be: “fread(&structVar, sizeof(structType), 1, fileHandle);”. fread()’s first parameter is of type void *, so it’ll take anything as a blob of memory. After this call, the struct variable is populated with data, and it’s easy enough to parse it by just saying “a = structVar.field1;”. Union types could also be used for parsing in memory.

In K&R C, if I defined a function, it’d look like this:

SomeFunction(arg1, arg2, arg3)
   int arg1;
   char *arg2;
   int arg3;
{/* some code */}

All the type specifiers did was tell the compiler where the offsets in the stack frame were. It cared nothing for types. It didn’t even care how many arguments I passed in to the function! I could’ve passed an 8-byte struct in for arg1, and not filled in arg2 or arg3, for all it cared. I could’ve accessed the first 2 bytes of my struct via. arg1, the next four bytes by arg2 (pointers were 4 bytes then), and the next 2 by arg3. The reason being that my 8-byte struct filled the stack frame the function was expecting. The struct could’ve been bigger. It still wouldn’t have cared. It would’ve caused problems, because then I would’ve had a stack overflow, but it didn’t watch for such things, just as an assembler wouldn’t have.

It wasn’t even that necessary to declare the function in a header file. If you called the function from another module, the linker would figure out what you wanted and just set up the call. The one time you needed to declare a function in the header was if you had a circular reference, where Function A called Function B, which called Function A.

Maybe there was a point to this madness, but I know it drove even some very smart people nuts. One possibility was you could use this property of functions to automatically do some of the work for you in separating a chunk of memory into pieces, so you could use the function arguments as a kind of template into it. It’s hackerish, again, but it would’ve worked.

Anyway, continuing:

Easily changed block scope (Suggested by Marcel van der Peijl )

    if( ... )

which, when adding debugging statements, becomes

    if( ... )
         /* the importance of this
            semicolon can't be overstated */
         printf( "Calling bar()" );
         /* oops! the else stops here */
         /* oops! bar is always executed */

There is a large class of similar errors, involving misplaced semicolons and brackets.

This is a programming 101 mistake. Come on! Put brackets around your code blocks, for cripes sake! 🙂 I’m getting the sneaking suspicion that the people complaining about this stuff are Python programmers.

I know Python determines code blocks via. indentation. I personally find this a little dangerous, because while I’m festidious about style, in a hurry, I sometimes just put aside code formatting to get something done, and then clean it up later. Worrying about formatting slows you down. Formatting doesn’t matter to C, delimiters do.

Unsafe returned values (suggested by Bill Davis <>)

char *f() {
   char result[80];
   sprintf(result,"anything will do");
   return(result);    /* Oops! result is
                         allocated on the stack. */

int g() {
   char *p;
   p = f();
   printf("f() returns: %s",p);

The “wonderful” thing about this bug is that it sometimes seems to be a correct program; As long as nothing has reused the particular piece of stack occupied by result.

Yeah, this is a mistake that’s often made by beginners, if they don’t understand stack dynamics that well. He’s right that sometimes this will work if nothing else happens to overwrite the stack. But there is an easy way to overcome this bug: make “result” static in f(). This way it will never be overwritten. Another method is to dynamically allocate the buffer for “result” (make the “result” variable a pointer) on the heap using malloc() (but you gotta remember to free “p” later in g()!). This way, only the pointer in f() is destroyed, but the buffer will remain.

When you’re writing in C or C++, you have to be more concerned with how the computer is executing what you’re going to write.

Undefined order of side effects. (suggested by michaelg@owl.WPI.EDU and others)

Even within a single expression, even with only strictly manifest side effects, C doesn’t define the order of the side effects. Therefore, depending on your compiler, I/++I might be either 0 or 1. Try this:

#include <stdio .h>
int foo(int n) {printf("Foo got %d", n); return(0);}
int bar(int n) {printf("Bar got %d", n); return(0);}
 int main(int argc, char *argv[]) {
  int m = 0;
  int (*(fun_array[3]))();
  int i = 1;
  int ii = i/++i;
  printf("i/++i = %d, ",ii);   fun_array[1] = foo;   fun_array[2] = bar;   (fun_array[++m])(++m); }

Prints either i/++ i = 1 or i/++ i=0;
Prints either “Foo got 2”, or “Bar got 2”

Yeah, this is a common problem with C/C++. It’s been there forever. I took a brief course on C in college around 1991. One of the things the teacher explicitly had us try out was an example like this. The moral of the story is never use l-value expressions (an assignment like ++i) inside of an r-value expression. In other words don’t do stuff like i/++i unless you really understand the hardware. You never know how it’s going to come out.

The reason I was told this and other such weirdness exists in the language is the language designers wanted to make it possible for the compiler to optimize for the hardware. This meant not locking down certain characteristics like this. If you wanted to predict what the compiler for a particular hardware platform would do, you needed to understand how the CPU handled sequences of operators.

Utterly unsafe arrays

This is so obvious it didn’t even make the list for the first 5 years, but C’s arrays and associated memory management are completely, utterly unsafe, and even obvious cases of error are not detected.

int thisIsNuts[4]; int i;
for ( i = 0; i < 10; ++i ){
    thisIsNuts[ i ] = 0;
    /* Isn't it great? I can use elements        1-10 of a 4 element array, and        no one cares */ }

Of course, there are infinitely many ways to do things like this in C.

Any decent instructional material on C would tell you to watch out for this. Again, C is just a higher level assembly language. No assembler would watch out for this, either. If you ran this code on a Unix system, you’d likely get a “segmentation fault” error (the operating system would terminate the process).

Octal numbers (suggested by Paul C. Anagnostopoulos)

In C, numbers beginning with a zero are evaluated in base 8. If there are no 8’s or 9’s in the numbers, then there will be no complaints from the compiler, only screams from the programmer when he finally discovers the nature of the problem.

int numbers[] = { 001, // line up numbers for
                       // typographical                        // clarity, lose big time                   010,   // 8 not 10                   014 }; // 12, not 14

Maybe this has changed. What I remember is that octal numbers were formatted with a backslash in front (I can’t represent it here). There are all sorts of type markers like this in C and C++. Heck, don’t start a number with 0x either, because that’s a marker for a hexadecimal integer. Don’t put an “f” after a number, because that makes it floating-point, etc.

Fabulously awful “standard libraries” (suggested by Pietro Gagliardi)

The default libraries in C are leftovers from the stone age of computing, when anything that worked was acceptable. They are full of time bombs waiting to explode at runtime, For an example, look no further than the “standard i/o library”, which, amazingly, is still standard.

  int a=1,b=2;   char buf[10];
  sscanf("%d %d",a,b);
  // don't you mean &a,&b? Prepare to blow!
  printf("this is the result: %d %d");
  // putting at least 20 characters in
  // a 10 character buffer
  // and fetching a couple random vars
  // from the stack.

I ran into this bug rather frequently because I didn’t use fscanf() or sscanf() that much. It makes some sense, though, because C passes everything by value. You have to pass in pointers to create “out” values. The reason this fails is that functions like scanf() and printf() allow a variable number of arguments (after the first one, which specifies formatting). Since the value types could be anything, the language could not restrict what types were in the argument list. Since variables are not references to objects, as in modern languages, but actual spots in physical memory, you had to distinguish what was a reference to a memory space (a pointer), and what was an actual value in memory. In this case, sscanf() wants a reference to a spot in memory, but Gagliardi is passing it int’s. Since C does not have runtime type checking, and since they’re coming in through a var-arg list, sscanf() cannot realize that it’s not getting pointers. It just has to assume that it’s getting them. In C++, it would be possible for a function such as this to do run-time type checking on the parameters and throw an exception if they weren’t of the correct type.

I don’t see this issue with var-args in C as a weakness in the standard library, but rather in the language. Functions like this still exist with modern languages, but today’s languages, with garbage-collected memory, use the concept of references to objects as the default, so there’s less of a problem (though it’s still possible to throw a function like this a curveball by specifying a certain number of arguments in the format string, but passing in fewer arguments in the var-arg list).

All of this reminds me of why I’ve sworn off programming in C as much as I can. I understand it, but I’ve grown beyond it. C is still used extensively in open source programming, from what I hear. I think in a way, C is returning to its roots. It’s good for writing things like operating systems, device drivers, and virtual machines, because those things need to interact with the hardware at an intimate level, and C certainly doesn’t get in the way of that.

I programmed in C for a couple years in college, and then for another 4 years out in the work world, and I was mainly using it for writing utilities, applications, and servers. In terms of software engineering for those things, it wasn’t the best language, but back in the 90s, it’s what a lot of places used for a while, before moving on to C++. I think the main reason it got picked was it represented a “happy medium” between high level abstraction and execution speed. In the 80s, if you needed it to be fast, you wrote it in assembly language. In the 90s, you wrote it in C. From my experience C++ didn’t get reasonably fast on the hardware available at the time until the late 90s.

Language compilers, interpreters, and VM environments are now written or translated into C, like Ruby, Java, .Net, and Squeak.  I’m sure there are some others. Squeak is a little unusual. The source code for its VM is in Smalltalk, but that gets translated to C and then compiled to generate a new version of it. In a way, C is becoming the new assembly language.