The Nature of Learning a Programming Language

A while ago, I took one of the tests from BrainBench. The particular test I took was the C Language one, and I was not impressed with it. I found that it asked questions whose answers could trivially be found with `man` without actually testing the parts of C programming I consider difficult or important. It would not have been an improvement if they had disallowed testees from consulting references while taking the test, as this would simply force them to memorize things that can easily be looked up, a waste of time. The point is to test those things which cannot easily be looked up.

What sorts of things are these? I'll start with an example. If I know the name of a function, I can easily look up its parameters and return value; there's no need to memorize this. However, if I know what I want to do, it's not so trivial to figure out which function to use. I may have trouble finding any functions which do what I want, or I may have difficulty deciding between some which seem similar (gets, fgets, scanf, etc.) These are the things which are time-consuming to learn (much more so than syntax), and they're also the things that are important to remember. Thus, the function to operation lookup is easy; the operation to function lookup is hard. It is the latter that must be tested, becuase that is what cannot trivially be looked up when one is programming.

It is, of course, impossible to do this with a multiple-choice test unless the number of choices is extremely large (at least several dozen). Thus, I do not primarily blame BrainBench for simply writing their test poorly; I believe that multiple-choice tests are simply not suitable for testing certain types of things, and programming languages are one of these things.

These thoughts also lead me to the conclusion that it is not possible to learn a programming language quickly (in a few days). It's possible to learn the syntax in a few days, but the whole reason the test didn't work well was that the hard part of learning the language isn't the syntax, it's finding the functions you want given what you want to do, and judgement about how to implement things. A number of people, however, seem thoroughly convinced that it is possible to learn programming languages quite quickly. My disagreement with them caused me to write the following:

Come to FooBar University; Learn Any Language in 3 Days!

What follows is a rant which I originally wrote for You can view the Article on Kuro5hin with other people's comments if you like.

I can't count the number of times I've heard someone say: "If you learn Computer Science, you'll be able to learn any programming language in a few days." Every time I hear it, it pisses me off. It pisses me off because it is total, unadulterated, ego-stroking bullshit that bears no more resemblance to reality than a deranged mountain lion bears to a cucumber.

I went to a prestigious university. I've seen a lot of CS grads up close. I've seen that a lot of them spend weeks getting to the "hello world" level when they get a job and have to write actual code. Never mind that, however. I'm not saying merely that many CS graduates happen to be incompetent; I'm saying that the very idea that a theoretical background lets you learn programming languages quickly is fundamentally broken.

If you want to write a program, there are three things you have to understand. You need to understand the algorithms you're going to use, the language(s) in which you're programming, and the platform(s) you are targetting. These are all learned separately. Let's suppose I'm going to write a Unix daemon in C. Algorithm knowledge lets me do things like store my data in a hash table instead of an array that I bubble-sort every time I insert something. Language knowledge lets me make intelligent decisions between functions like sscanf or atoi, and prevents me from writing 'printf ("user supplied string");'. Platform knowledge is what tells me how to use things like socket() and bind(). If any of these three are lacking, my program will suck.

Now, let's consider what you learn in a theoretical CS program. You learn lots about algorithms, so that part is covered just fine. You don't learn a damn thing about real-world platforms, but that's not the subject here, so we'll assume that you learn all about those on your own. This brings us to languages. They don't teach real-world languages in theoretical CS, so all you can learn is general information applicable to multiple languages. You learn the fundamental concepts of procedural and functional languages (and possibly other types as well).

Now, this is important, especially the part about functional languages. We understand functional programming! We're much better than all those self-taught procedural-language code-monkeys. All they can learn is the syntax, but we can appreciate the beauty and elegance of the underlying principles. Let's sit around and feel special. Go ahead, feel special. Please. Get it out of your system.

Now that you're done feeling special, I'd like to point out that this isn't the hard part of learning a programming language. The devil, as they say, is in the details, and this is very true here. The hard (or at least time-consuming) part of learning a programming language is not in the basic theory. It's in learning about the functions (or standard library) that the language provides. You may think that there isn't a whole lot to learn here, because you can always look things up when you need them. This is both true and false. I'll take the example of C. If I know the name of a function, I can figure out its syntax quite easily, using 'man'. However, if I know what I want to do, it's nontrivial to find a function which does it. That's what you have to learn. I don't need to remember the syntax for, say, memset (does the value come before or after the size?). I need to know that when I want to set memory to a particular value, memset is the function I should look up. This comes from experience, and knowledge of the particular language in question. This takes time. What takes even more time is the ability to make intelligent decisions - do I use scanf, or write my own parser? How do I divide the code into files? Which functions would be better as a preprocessor macro?

What about other languages, like, say, Common Lisp. You can learn common lisp in three days? You can't read the Common Lisp spec in three days! I won't even talk about C++.

Yes, Mr. Computer Scientist, you can be more skilled than the person who taught himself a language without any background. However, you don't get there for free. You get there by putting in just as much effort to learn the language as he did, in addition to your theoretical background. If you understand the theory and not the language, you're no better than the person who understands the language and not the theory - you're just differently incompetent.

I don't doubt that you can learn just the syntax of a language in three days. In fact, you can probably learn the syntax in three hours. Trying to program knowing only the syntax and algorithms is like trying to drive to the other side of the world with perfect directions and maps, but without understanding what the wheel and pedals do. Saying that you can learn a language in a few days is like saying that because you understand the theory behind transportation, you can trivially learn to drive any type of vehicle. Go drive a stick shift with no experience then come back and tell me that with a straight face.

If you think you can learn a language well enough to write reasonably good programs in three days, you're simply wrong. The CS professor who told you that you could was wrong too, probably because he's never done any actual programming in his life. It takes time to learn a language properly, regardless of how many other languages and abstract theory you know.

I don't doubt that there are people who genuinely believe that they can learn programming languages in three days. I also don't doubt that they have never properly learned any languages at all and write very, very bad code.

I'm not saying that there aren't legitimate, valuable contributions that one can make in the real of computer science without writing any real-world code at all. There are. If that's what you want to do, I have only the greatest of respect for you - as an applied mathematician. Just don't pretend that you can actually program a real-world computer when you can't. Every time someone claims to be able to learn a new programming language in a ridiculously short amount of time, it not only makes the speaker look dumb, it's an insult to everyone who has actually put in the time to learn to program properly.

It's the same in other disciplines. A great number of engineers look down on machinists. They think that they understand the principles of the machines, and the machinist is just an operator. Then, one day, they have to do the machinist's job, and they can't. The then learn the lesson that the application of theory is a skill in and of itself, and does not trivially follow from the theory. It's a lesson that theoretically-minded people of all sorts must learn sooner or later in order to be worth anything, and many never do.

A century from now, there will probably still be people who understand the theory of something and assume they can trivially learn to apply it. A century from now, they will still be wrong.

For more along the same lines, see Peter Norvig's writings