More on Thinking

In our last episode, I waxed eloquent on the significance of writing as an instrument of intellectual exploration that triggered the cultural explosion of classical Greece and set Western civilization barrelling down its current path.

My point in this essay is that the computer offers us a similar but less glorious opportunity to change civilization. That's a rather exalted claim, I confess, but hear me out.

What is the real significance of the computer? Is it a monstrous number-crunching machine, cold and inhuman, ready to obliterate humanity for computational convenience, as we pictured it in the 60s? Is it a source of cheap thrills as a videogaming machine, as we saw it in the 80s? Or perhaps an office machine, a glorified typewriter? Just what is this thing, anyway?

I'd like to turn the picture upside down and suggest that we're asking the wrong question here. Imagine yourself in 1469, examining one of the new-fangled printed books, trying to divine the real significance of the technology. You might be tempted to focus your attention on the thing itself, the physical entity of printed page, but you would be wrong. The importance of printing was not in the printed page itself, but rather in the ideas unleashed by the printed page. In the same way, when we wonder about the significance of the computer, we are misplacing our attention. The computer is just the paper onto which and with which we write; it is no more important than the paper onto which Gutenberg printed his first Bible. Necessary, yes; but not the essence of the revolution.

What was important about printing was writing, the gathering, publication, and group consideration of ideas. What is important about the computer is programming. Programming is the new writing. I don't mean to suggest that programming is a new form of writing in the same way that algebra is a new form of writing, or musical notation is a new form of writing. No, programming is much bigger than these examples, because it permits expression and exploration of ideas on a very different scale than conventional writing. Now, many of you are not programmers (thank God!) and so you might not appreciate just how radically different programming is as a form of writing. I'd like to expend a few extra electrons to explain some of the cogitative advantages of programming. I recognize that, as non-programmers, you won't be able to grasp my points from direct experience, so I will ask you to take my word about the powers of this new kind of language.

One big idea that programming handles very well is abstraction. Now, conventional language has abstraction, too, but it's a loosey-goosey kind of abstraction. We can have chair - furniture - object, or cat - mammal - animal, but we can just as easily have chair - manufacture - asset or cat - pet - companion. Abstraction presumes taxonomy, yet the taxonomies used in natural language abstraction are arbitrary. This isn't necessarily bad, mind you -- it is a source of great flexibility. But in programming, abstraction is tightly defined by a clear sequence: constant, variable, pointer, and handle. You could conceivably extend the sequence even further, but nobody seems to have needed to do so, because these four levels of abstraction completely address all the problems we've encountered so far. It's not that programming languages are narrow-minded where natural languages are open-minded -- try using "ain't" or "I is happy" in front of peers and watch your social status drop a notch. There are some situations where precision is essential, and even natural languages can get rather prissy in such situations. Where natural languages can demand precision of tense, number, gender, or case, programming languages demand precision of abstraction. And this greater precision of abstraction permits one to think about issues of abstraction more clearly and powerfully, just as a strongly conjugated language allows one to express ideas of action with greater clarity.

Another concept that is well handled in programming is nonlinearity. All thought processes involve a certain amount of nonlinearity; sequential thinking need not be linear. Conventional writing must struggle to cope with nonlinear needs. We have developed glosses, footnotes, parenthetical remarks, sidebars, and all manner of other means of coping with the need for nonlinear explication, but these are all band-aid repairs, ad hoc solutions tacked onto a system that is fundamentally linear. Programming, by contrast, has nonlinearity built into its deepest structures; the basis of this nonlinearity is called "branching", and all programming languages, even the simplest, have some form of branching. As with abstraction, branching is conjugated in programming with all the rigor of a Latin verb, and enjoys the same expressive precision. Latin permits fine nuances of interpretation of action to be expressed with verb endings; programming permits fine nuances of branching to be expressed through its branching structures. Indeed, nonlinearity is so easy, and so powerful, that much of the history of programming language development has been a story of learning how to rein in nonlinearity. Early programs in machine language jumped all over the address space of the computer in what was disparagingly called "spaghetti code". It sure seemed powerful, but it was also impossible to keep track of. The concepts of structured programming, modular programming, and object-oriented programming were all developed to make nonlinearity more understandable and more controllable.

A third programming concept is looping, which can be thought of as a special case of branching. A loop in a program will repeatedly execute some simple action many times, with some tiny difference each time, that difference spelled out by the program. This concept seems minor but it is central to programming; indeed, any program lacking loops isn't worth writing. Perhaps the biggest mental shift one must undergo in learning to program is thinking about problems as loops rather than chunks. For example, when your computer puts an image onto the screen, you probably think that it is "putting an image onto the screen". Silly you! What it really does is a loop. It grabs one number that represents the color of a single pixel, then it calculates where in screen memory to store that number, and stores it. Then it grabs another number, and another, and another -- several hundred thousand times, depending on the size of your image. The human mind boggles at the thought of doing the same thing over and over a few hundred thousand times, but the computer would boggle at the thought of "putting an image onto the screen". Human thinking is chunky where computer thinking is loopy.

Actually, computer programming does entail a notion of chunkiness (we call it "modularization"), but it turns out to be a mental discipline to help the programmer; the computer itself could operate just as well with no modularization whatever. Nonetheless, the concept is useful and interesting. For example, one manifestation of modularization is called "scope"; it addresses the range of applicability of shorthand terms. Now, natural language has the same thing, but it's so poorly defined that it is just as often a source of confusion as clarity. Pronouns are the most immediate manifestation of this process in natural language. A pronoun is certainly a handy shorthand for longer names, but it only works if you know who the pronoun refers to. This can get confusing sometimes. For example, if I launch into a discussion of Desiderius Erasmus, then digress to other matters, then refer to "him" twenty sentences later, will you be able to remember that I was talking about Erasmus? You say that twenty sentences is too great a distance? OK, where do you make the cut: at ten sentences? Five? Two?

This problem occurs not just with pronouns but with all sorts of other shorthands. My wife Kathy will muse to herself and then blurt out, "Do you think we should visit Linda?" To which I reply with just the slightest edge in my voice, "Which Linda were you thinking of?" The unstated message being "You really should inform me of the context before involving me in a discussion."

Ah, but with programming, these problems vanish forever! In object-oriented programming, you have three well-defined contexts for every variable: global, member, and local. A local variable applies only within the confines of one particular function; it means nothing outside of that function. A member variable applies only within the context of an object. A global variable applies over the entire program. If you wish, you can define intermediate levels of context by establishing a hierarchy of objects; thus, if three levels of context aren't enough, you can have four, five, or as many as you wish. Now isn't that a better way to use context?

Now I'm going to attempt to explain an idea straight from the Inner Sanctum of Programming: recursion. This is a concept with absolutely no analogue in natural language; it is quite difficult for nonprogrammers to appreciate -- and among professional programmers, it takes years to master the concept. Recursion is a method by which a function solves a problem by repeatedly calling itself until it reaches the core of the problem. I'm not going to attempt to explain that; it's so weird, so alien to normal human experience, that natural language fails to communicate its substance. I think that the best explanations of recursion for our purposes will use metaphors. All problem-solving with the computer is intrinsically analytical in the sense that you break the problem up into little tiny pieces, solve each of the little pieces, and assemble the solution-fragments into a whole solution. In most cases, however, the process of breaking the problem up is done with the intellectual analogue of a slicer-dicer: you chop the problem up into equal parts that sit next to each other in a nice, clean row; then you work your way down the row with a loop. But with recursion, you break the problem up from the outside in, without even knowing what the inside holds. The cleavage lines of analysis in recursion are layers of the problem rather than ranks and files of the problem. What people find so confusing about recursion is the notion that you set up the cleavage lines on an outer-to-inner basis, even though you don't know what's inside. Instead, you must abstract the nature of what's inside and write your cleavage lines -- recursion levels -- to exploit whatever abstract rules you can impose on the solution.

You're probably just as confused as I was when I first encountered recursion. The point I want you to take home is this: recursion is high-powered intellectual stuff, that makes perfect sense in the world of programming, allowing you to think about problems in a completely new color. You thought that red, green, and blue were the only primary colors? Think again -- programming gives you a new set of glasses to wear, glasses that allow you to see the universe of ideas in a new light.

So here we have in programming a new language, a new form of writing, that supports a new way of thinking. We should therefore expect it to enable a dramatic new view of the universe. But before we get carried away with wild notions of a new Western civilization, a latter-day Athens with modern Platos and Aristotles, we need to recognize that we lack one of the crucial factors in the original Greek efflorescence: an alphabet. Remember, writing was invented long before the Greeks, but it was so difficult to learn that its use was restricted to an elite class of scribes who had nothing interesting to say. And we have exactly the same situation today. Programming is confined to an elite class of programmers. Just like the scribes, they are highly paid. Just like the scribes, they exercise great control over all the ancillary uses of their craft. Just like the scribes, they are the object of some disdain -- after all, if programming were really that noble, would you admit to being unable to program? And just like the scribes, they don't have a damn thing to say to the world -- they want only to piddle around with their medium and make it do cute things.

My analogy runs deep. I have always been disturbed by the realization that the Egyptian scribes practiced their art for several thousand years without ever writing down anything really interesting. Amid all the mountains of hieroglypics we have retrieved from that era, with literally gigabytes of information about gods, goddesses, pharoahs, conquests, taxes, and so forth, there is almost nothing of personal interest from the scribes themselves. No gripes about the lousy pay, no office jokes, no mentions of family or loved ones -- and certainly no discussions of philosophy, mathematics, art, drama, or any of the other things that the Greeks blathered away about endlessly. Compare the hieroglyphics of the Egyptians with the writings of the Greeks and the difference that leaps out at you is humanity.

You can see the same thing in the output of the current generation of programmers, especially in the field of computer games. It's lifeless. Sure, their stuff is technically very good, but it's like the Egyptian statuary: technically very impressive, but the faces stare blankly, whereas Greek statuary ripples with the power of life.

What we need is a means of democratizing programming, of taking it out of the soulless hands of the programmers and putting it into the hands of a wider range of talents. What we need is analogous to an alphabet. And that's where I'll leave you until next essay.

 

Home / Library / Lilan Index

Related essays:

History of Thinking Part 1

History of Thinking Part 2

History of Thinking Part 3

From Parallel to Sequential Thinking

What is Recursion?

Programming for People