Wednesday, November 5, 2008

Self-reference and Statistical Density

Programming languages are ways of mapping between three things: a set of problems in some problem domain; a set of envisioned solutions to those problems in a computer programmer's mind; and a set of instructions that can be executed by a computer.

Computers are very stupid, and not at all lazy. Programmers are very lazy, and hopefully quite smart. So, the language has a big gap to close.

For example, suppose I have an object that stores some numbers "a", "b", ..., "y", and "z", and I want to provide "fudge" and "muddle" operations on these numbers. I could write functions called fudgeA, fudgeB, muddleA, muddleB, and so on. Boring! Once I've written the code for fudge and muddle for A, I'd really like to just say "and do the same thing for the rest". So I want a language with that sort of expressive power, a language that can contain concepts like "the rest" and "the same thing". A language, that is, that can refer to itself, not only to the entities in a problem domain.

Taken to the extreme, what this leads to is programs of maximal statistical density: that is, programs that contain no repetition, but lots of self-reference and automatic code generation. There may in fact be many nested layers of this stuff.

As with Zappa's opus of statistical density, The Black Page, the problem in practice is that this becomes devilishly hard to play. Highly self-modifying programs save the original programmer's time, but generally make life for everyone else worse. The goal of making code more concise is seriously flawed. The goal should be to make code more understandable, not more concise.

I say "generally", because there's one case where it works. That's when the self-referential features of the language fit with the way that programmers think about solutions. For instance, "do the same thing to all these numbers" is the way that a programmer would typically describe the solution; to have to spell out each function separately isn't just repetitive, it makes the program code be less like what's in the programmer's brain in the first place.

My point is that I think that language designers should learn more about how human minds work, and should prefer native constructs and shy away from constructs that require unusual intelligence and training to master. Computers do not think like people; so programming languages need to.

There is a lot of overlap between computer science and cognitive psychology, but so far as I know this premise has not been applied; quite the opposite, it seems that new programming languages are more often used as a vehicle for showing how smart the programmer is.

Specifically, there are certain constructs that are demonstrably hard for most people to reason about. The ability to reason about recursion, for instance, is often used as an interview test to separate the "real programmers" from the mediocre. Recursion is actually one of the few things that computers innately know how to do, so it's not surprising that it's in computer languages too; but if it makes it so that only really smart people can write good programs, then I think it's something we should be trying to get rid of, not use more of. If a car is hard to steer for people of normal strength, we give it power steering, we don't just assume that Driving is a job open only to the abnormally strong.

Of course, I'm blowing into the wind here, because cognitive psychology has not held up its end of the deal. Language designers can't learn much more about how the mind works, because cognitive scientists haven't figured it out yet either. We know very little about what processing contructs are "native" to the mind.

But as a starting point: three things that seem hard for most people are feedback loops (that is, control theory, home of things like proportional-integral-derivative algorithms); recursion (especially if the rules change depending on the depth); and n-dimensional geometry. Electrical and industrial engineers get advanced training in handling feedback loops; I've never met a computer scientist who has, and I've never met a non-specialist who has. Physicists and mathematicians work with n-dimensional manifolds, but EEs and programmers rarely go beyond three. Programmers get advanced training in recursion, but no one else does. In each case, the fact that training is required and that these are all exclusive fields says something about the cognitive difficulty.

The question is not how we can make programming more efficient for a vanishingly small number of people. The question is how we can make it more efficient for a larger number of people.

No comments: