"...NetworkedGraphicsMV3500.git" did not exist on "d13814a0b6ae94d4ef8f93d32d70f239e1f8d6fb"
added the first transcript
Compare changes
transcripts/Hamming04_Transcript.txt
0 → 100644
+ 83
− 0
Shall we begin? The talk today is on software. Software got its name because hardware you could lay your hands on, software were the programs which told the machine what to do and they were somewhat soft. They got that name for this contrast with the hardware which you could lay your hands on because in the early days of machines people didn't really understand machines. Software is what tells the machine what you want done. That's some totalment. Now in the early days with hand calculators, you turned a crank, and you threw the carriage over and so on, and you controlled it by your hands. And the early IBM machines were plug boards. You put wires from the columns and the cards to where you wanted in the machine. From where the answers were in a machine to where you punched on the card or where you want it printed. We wired up single boards and in the accounting room for example, each operation would have a board. It would be stored away, so each week we went through the accounting process, you picked up the same boards. You didn't rewire them because they were rather troublesome to wire - to say the least.
Now after George Stibitz’s first machine. He used paper tape and paper tapes are a terrible thing to use. You can't make insertions very well. When you glue the tapes together, the glue gets stuck in the fingers of the readers and its troublesome but you won't see much anymore. The ENIAC in ’45 – ‘46 was the first electronic machine. And it was designed to do integration of ordinary differential equations for trajectories to build bombing tables or ballistic tables. Well, that was the design and so it was designed pretty much like a glorified IBM plug board except the machine was in a room about this big and the cables went all the way around on trails around the room.
However actually the first problem run was part of the original studies of how to build hydrogen bombs. So the machine was used differently. And in fact, the way they wired it was so awkward that ultimately Metropolis and a guy named Dick Clippenger devised a method of wiring machine once and for all. So you then program from the ballistic tables and really set numbers, and that would be the program instead of rewiring it all the time.
Now real internal programming became a reality when we had registers. We began with machines with two and three registers. We got up to ten or twelve or fifteen - that was a lot. Well you can't do internally programming then. I am inclined to believe that people thought about it. When we got enough internal programming space so we could really write out programs, they began to discuss it as had Babbage. Now what happens is that von Neumann was hired as a consultant and he wrote up the reports on how to program and so it's attributed to him. But Harry Husky’s written that they had discussed internal programming long before von Neumann ever was a consultant. Watching around, von Neumann never either claimed he had done internal programming or denied it. So since he’s dead you're left. But my inclination is that attributing the internal programming to von Neumann's is probably very dubious.
Now in the early program, when you program absolute addresses. If there were an error here, you want to put something in, you took that instruction, replace with a transfer, put that one over the transfer place, put down the additions and transfer it back again. Now when you found another error over here, you do the same thing. And pretty soon the control was like a can of spaghetti. All over the memory in very strange ways. And it became very, very hard. And we lived with it for a long while.
Now we very rarely got the idea of reusable programs, even Babbage had the idea. We called them libraries in those days. We ran our square routine, we put it in the machine and we reuse it. Everybody wants to use the same one and we put them in definite locations at first. But if the score routine is in that location, and the sign is in that location, and so on, you've got to program around all those parts. And pretty soon the library is so big that it all can't fit the machine at once. So we turn to relocatable software which was in the von Neumann reports. The von Neumann reports were Army reports. They were never published officially. They were just issued and everybody had a copy. But they were never really refereed and published. The first published software book was on the EDSAC out of Cambridge. I told you I think that in 1946 Mauchly and Eckert held an open session and told everybody everything they knew about how to build computers. And Wilkes, Maurice Wilkes, of Cambridge was there. He attended the thing, went home and he built a machine and got it going before anybody else did. So his was the first machine and his book, which we'll talk about several times, was the first programming book.
Now pretty soon somebody had an idea that I could write a program which would take the letters ADD at read time, when it was reading into a machine, and convert it into the pattern of zeros and ones which was the crazy instruction the designers had built. And so we had symbolic addresses. Our symbolic names, converted. And then somebody said, well we could do the same with addresses. I could call the address A and you could let the machine assign that and the machine will remember where A is. Every time we refer to A it will give the absolute addresses. Those were primitive assembly programs, and what you tend to call machine language, but that really is a fancy business, already.
Now that went along for a while until a very much better one called SAPs, Symbolic Assembly Programs, was written which really did a job fairly well. Now we were using IBM 701. That was expensive. I calculated this morning coming in, we paid $300 an hour to rent it. Since there's been inflation, ten to one, that's something like 3,000 or more dollars per hour which is something like almost $1 per second. So you can see why we tended to economize on machine time and not worry about human time. At a dollar a second it’s kind of expensive. Well I spent one year, with the aid of a lady who did most of the work, filling up 32,000 registers of the IBM 701 with a program. And at the end of the time I said I will never again ask any human being to do a job like that. It was just awful. She did it very, very well. I'm not complaining. But it was not fit human being living. I had heard about a symbolic system up at Poughkeepsie, so I said to her, next program send up for that and get it. We sent up for it, they sent it down, it didn't run. Why? Nobody had ever used it. Well they helped us, got it going. Now at IBM headquarters, there were about a hundred of us using the machine. About 50 IBMers, about 50 like the young lady and myself, who are outside coming to use the machine. They gave us office space, nicely. We all ate in the cafeteria most of the time. Although every once in a while I'd go to lunch with the guys rebuilding Fortran and we'd go out to a fancy restaurant. Well we told these people, and it must been 100 of them, only one so far as I never could determine was interested in a symbolic system. All the rest of the programmers wanted to use the same old absolute binary program they always used. It was too wasteful machine time, they said.
Well programmers were very, very slow in adopting the better methods. When Fortran came by, which means Formula Translation written by Backus and a bunch of friends. They set out to do what people normally do - translate high school mathematics, along with a few calculus words, into the machine language. They wrote what I will say is a psychological language. They designed it to fit people. Now when they started people said it can't be done. If it can be done, it'll be so inefficient you can't afford it. In any case even if it could, nobody but sissies would ever use Fortran. A good man code were right square in machine language. Well, that’s the way.
Now along about 1958 ACM with a bunch of logicians got together back to think language called Algol. I was involved in a sense that I was president of the ACM at the time and had to find the money to send Al Perlis to Europe to have a world conference on how to design the language. Well they designed it. It was logically beautiful. It was written in logical language, of Boolean logic, which normal mortals can't read - even they couldn't read sometimes. Well it was supposed to be the great savior. Well you know the situation. Fortran is still around and you haven't seen the Algol program for years. Why? Because I say Fortran was designed psychologically and Algol was designed logically. Those programmers who design logical languages don't get their language to last long. When you come around designing a language don't let a logician design it. Look at the people who are going to use it. Ask how they think and design it psychologically to fit them. The tremendous survival of Fortran tells you. The value of psychological design of language as against logical. Logical just isn't very good.
Now along, oh that was beginning of a time when we had POL, Problem Oriented Language. We had a whole bunch of those for a while. One for doing this, that and the other thing. The trouble was, if you had a problem doing two of them, two different things, the program languages didn’t blend together very well. So we gave up the idea of writing special languages for special areas of problems. We still do to some extent to have business languages and scientific languages as we had, but ADA as you know is an attempt to be a universal language. Now ADA was designed by a bunch of programmers and in my opinion it suffers exactly that fault. It's a nice logical language but it's not fit for human use. And it's not really going to work out too well.
Now I tried out an experiment. You know the government frequently lets out contracts that shall be written in ADA. So I call my friends who were involved in running software houses and said how is it going to work out? Will it work out that the programs are written in Fortran, debugged and got running and then converted to ADA with all those mistakes? They said yeah about ninety percent of time. And I suspect that something like that is happening right now. Although the contract says you shall do it in ADA it is very likely it'll be done in Fortran. And then converted over with all those attendant mistakes.
Now in 1962 LISP language began. McCarthy thought of a language designing for logical reasons and it was improved and extended by various friends logically, abstractly. A student one day said hey I could write an assembler in LISP language itself and cause it by and large to assemble itself. McCarthy said, you could? He said sure, so they did. It’s one of the first examples of using a language to assemble itself. It's a very useful technique.
Now let me digress and talk about the 650 machines I used. It was a 10 decimal digit machine with a drum. And so therefore it was a two address system instead of the typical one-one. The first address told you where to find the number or put the number, and the second address told you where to find the next instruction. So you could carefully arrange it so as the drum came up there, right as you’re ready to read, that instruction was there. Rather than having to go all the way around to find next one, you could place them just so they would be right. And the machine would operate much faster. That of course also depended upon where the numbers were put. When you put them here, there, yon, it had to be right where you want it, when you want it, then it would run very fast. Otherwise, it would go around and around and do very little. So the problem of what we call minimum latency. How do you design a program to store here, there, yon so it will run as fast as you can make it?
IBM produced a SOAP program, Symbolic Optimizing Assembly Program. They made two copies. They rode off straight up. Call them copies A and A. They loaded A in the machine and they ran A through it to get an optimized SOAP. Then they loaded the optimized SOAP in and ran A through again and observed how much faster the second pass was to the first was so you know how much SOAP did in improving the thing. Another example of a program which optimized itself. This business of using programs to do themselves have proved very popular very, very effective and you want to think about the recursive aspect of how you can make a lot of work be done by the work you're doing. It's a very powerful technique.
Now let me talk about that book from Cambridge, England. I reviewed the book. In Appendix D there was a little program which had been written because the program man wanted to write, could not fit into memory. So I wrote a little piece here in brittle of translation there. It was an assembler. It wasn't called that, but that's what it was. When I reviewed it, I stayed over it a long while and realized that's what it was. If they put Appendix D did they know? In the second edition, it was still in Appendix D. Did they know what they've done? No. I'm raising a question, when is something known first? We tend to give credit to the first person who says something but that really isn't right. There was a time when I and a bunch of other people in computing realized one day that computers really were not number-crunching machines. There were symbol manipulating machines. We went out and gave talks. And I could watch the audience nodding their heads all yes, and I knew most of them did not understand what I was saying. They did not understand they were not number crunchers there were symbol manipulators. But that's the way it goes.
Now you can say originally Touring's machine back in 1937 was and demonstrated similar manipulation. That's what it was. And you can also claim, if you wish, that he must have understood interpreter because that's how he proved that every machine was equal to any other machine. The universal Turing machine was really any one of the machines with a suitable interpreter. So he must have known, but did he? The answer is no, probably not. Now history tends to be charitable and give the first guy credit. There's a saying however, that says almost everybody who creates a field never understands it correctly. They apply a certainty of physicists. Many physicists have created a field and then they have been a drag on it. Einstein started quantum mechanics going but he never accepted quantum mechanics. He always opposed it. He didn't believe that God played with dice as a famous saying of his was.
Well turning back to 650, having realized the machine was ten decimal digit machine and I want a floating-point and that was a fixed point machine, I would have to build an interpreter. So I hit upon the following idea. Of the ten decimal digits I would use three for A, one for the operation, three for B and C. Take the number that's in location A do this operation, would be like add, subtract, multiply or divide, and put the answer in C. I have four instructions but of course, only four of those, add, subtract, multiply and divide need both addresses. If I put a zero in here, the machine would look here for further information. What instruction you wanted. So I had a whole bunch more instructions. Well now I wrote this program in my mind. Start, you assign some register the current address register. You go there to find out where the instruction you want to obey is. You go to that location, get the instruction. You store the A, you store in the B, you store the C. You take the operation, add a constant to it, transfer. Here you find a subroutine describing an operation. Here's a bunch of which were transfer instructions. When these were done, they transfer to here. You added one to the current address register. You went back to start, after cleaning up. If it were a transfer instruction you transferred to here. Now you see, I have not told you the language. I've told you how to build a language. All meaning is contained in what those subroutines are, correct? Everything is contained in here. What do those instructions mean are what you put there. You can write any language you want. Now that was a language where every instruction meant what it meant, without any contingent about what went before or after. You could easily arrange, I could have, that if this is structural bait it sets a flag, when this is structural goodbye it looks at that flag, oh then do this if not, do that. I can make a language which depends about context. I didn't, this was a context-free program. But you see how you do it. I want to dwell on this. How utterly simple it is to build an interpreter. Now differences between an interpreter and a compiler is very simple. An interpreter does it and every time you come to the same instruction loop you do the same translation. A compiler makes the translation once for all, writes out the translation and then runs the problem. And there are subtle logical differences between the two. You've got to be careful, but fundamentally that's the idea. And for machine efficiency we usually make a compiler but if you’re going to do floating point, you have to really do this. I'm sorry, you have to be a compiler. You have to be an interpreter for floating point because you don't know which numbers are going to be where, how much you have to shift back and forth. You can't really build very good one. So sometimes you build interpreters. Sometimes you build compilers, and now we build compilers on top of compilers and interpreters on top of compilers and so on. We do this all the time. This is how we make a machine look like what we want. And I think it should be clear to you, if you can define a language, uniquely, write out the subroutine, write out something like that, and you have now the machine behaving in this language.
Now one thing I did was interesting. The machine had 2,000 registers. I put all this in the upper 1000. This machine, these three addresses, could never refer to anything other than the lower 1000 registers. There was no way your program could interfere with the stuff I had written. I had built in safety. Protection against stupidities on your part was protected with that simple method.
Well now, I say I understood the thing. I learned it from somebody else. I say they didn't understand it. That's that funny thing, I want to say is very common. Almost everybody in physics has done this. Now take myself, you know I suppose that I'm the father of error correcting codes. Well some guy who knew me said to another friend, “You know, I don't think Hamming ever understood error correcting codes.” A friend of mine repeated to me over the phone, I was just about to say “Why that..” and I shut up. And said over the phone to him and I said “Yes, he is probably right.” The person who discovers something rarely understands it. They had their feet so far in the back and all the trouble they had they don't see the light. Whereas the people who come afterwards see it much more clearly the person who did it. Perhaps the best illustration of this point, besides telling you my personal story, is Newton. It has been said Newton was the last of the ancients. He was not the first of the moderns. Almost all creative people when they create something do this. So the reason we're telling you is twofold, if somebody else has created a field and he said this is the way to do it, you're entitled to ignore him. On the other hand, when you create a field, remember to shut up. You don't really understand what you did.
Now I started that method with four rules: easy to learn, easy to use, easy to debug, and easy to use subroutines. Now let's skip the fourth one because it's tied up with the crazy ideas we had about subroutines which are of no use to you whatsoever. It would appear that I was doing top-down programming. Easy to learn, easy to use, that's where I'm going to start. The first thing I did was to write essentially this inner loop. I wrote it down in my notebook. In other words, I went from bottom up. I wrote the very bottom. Once I was convinced that this could be done rapidly enough, then I went to top down again. So while I like top-down programming, I know that you have to do bottom-up also occasionally. There are a million methods of writing programs and we'll talk about various times.
Again I want to point out the difference between logical and psychological language. This A operation B equals C was something. Remember that said the number in A times of all what number B is to be put in C. It was going to be programmed by a bunch of high school graduates to a great extent. They weren't logicians. Machines were not common. I wrote a language that was easy to understand not only for them but for a second reason. I understood the problem by that time of what it really was. Machines were not widely known. They were being used in physics but if you don't know what machines can do and can't program, you don't know what kind of questions to ask. And so the problems coming in were all problems that they would have done if they had been no machines except they could do it faster. My problem was to get a language so easy that the physicists and chemists and engineers could not refuse to learn it. Once learned it, they would know how to ask the appropriate questions. That was a problem I really grappled with. How to make a language so easy that PhDs in physics can understand it, not programmers.
Now I understood a great many things about things that aren't usually discussed. I want to point out one feature, a language called APL. It was again devised by a logician, originally devised to describe circuits, but he developed it into a language. Now APL has its devotees and has people that can't stand it. The characteristic of APL is it's very, very terse. You can write one line of programming and change a comma or something, and the whole thing is different. Well people who like it, like it because it's very simple. You write it out and you write very, very little and you get a great deal for it. People who don't like it, don't like it because you make one mistake, you get something completely different. It has almost no redundancy.
The language I'm talking to you now has about 60 percent redundancy, meaning you can drop about 60% and still make it out. It has to be this way. I'm talking at a rate you have to grab it on the fly over an acoustic channel. Now the written language is different. It's about 40% redundant because you could stop, you could back scan, the channel is not anywhere near as noisy. If you think the written and spoken language are the same, try writing dialogue and see what happens to you. You can't write the language you speak. I know you think you can, but you can't. There are different languages and when you do find a book with dialogue it sounds very good. It really is not how people speak. So we really have a couple different languages and redundancy is necessary. If you write a very, very compact language with very low redundancy, it's not fit for human use. If you write one with very high redundancy, it takes too much time to write the stuff out. So you have to find your way between those two.
Well, I was interested in the matter because I knew we were writing languages for machines. So I invited Professor Pei of Columbia, who was a very popular linguist, down to meet me at IBM headquarters at 590 Madison Avenue and I would take him lunch after. So we showed him a machine, all the glamour, and we took him to lunch. In a dessert time, I said, “Well Professor Pei, we are regularly inventing new languages to work with a machine. It's a language between machine and humans, human to machine and later on, maybe machine to human. What can you tell me about the engineering efficiency of language?” He could not understand the question. He could tell me how some languages put plurals in the middle of words. He could tell me all kinds of things, about all kinds of languages. But the only thing I wanted to know is, how do I write an efficient language for communicating to a machine with enough redundancy? Why do we have the number of synonyms we do? Why do we have the antonyms? Why do we have irregular, regular verbs? Why? What are the values? Now there is a presumption that the languages we are using are reasonably well designed to do the job that they're doing. Not certainly, but it's a reasonable presumption.
Now the language we use it for is not what you think. And this may be a bit out of place, but one of my favorite stories about my wife and myself when we were in New Jersey. Our dining room table, was the breakfast table, right next to some windows looking on the garden. We're having breakfast prior to me going to work and she says Dick it’s raining. I look at her and think, what's wrong with that Dame? She must know that I can see it's raining. Then I said to myself, what did she really say? What she said was, I've had my second cup of coffee and I’m fit to talk to. Well I spent much of that day at Bell Labs watching how much of what we say is not what it appears to be. And it's amazing. The enormous amount of what we say is literally not correct. No way. So the languages has a great many other things than what you think. Our natural language has a great many other features which a language to a computer would not have to have.
Well we have not studied the problem. When I heard the Japanese were planning to write fifth generation computers, the speed was all right but when they're going to use AI to do things, I thought they would not succeed they didn’t because they were not profoundly studying the nature of language. And until we do, we will get languages like ADA which are logically all right but they don't fit the human animal to do the kind of things the human animal does with language. It's a very, very miserable thing.
Now I point out there are two languages. There is you to the machine and the machine back to you. They need not be the same language. You want a terse one in and you're willing to put up with rather more verbose one coming out. Frequently what comes out is so terse you can’t figure out what it means. You’d willingly settle for much more print out but not too much. So it's a problem of designing language. You communicate ideas to machines, but unfortunately we don't know what ideas are, so we don't know how to do it.
Now I made a prediction at Los Alamos for them when I was there visiting once for two weeks. That the fifth generation would in fact do what I told you the other time, the machine hardware fell right on the curve the software was a total flop. They did not get anywhere using artificial intelligence to make programming easier. No way. We don't understand what we're trying to do. Now you read continually about engineering software because software is a major problem for everybody. It sounds nice. But, should I believe it? Let's consider some situations. When the Russians and the Americans want to get out into space they did things pretty much the same way all things considered and allowing a little bit for espionage. But if I asked a couple novelists to write on the greatness of misery of man, I claim I'll get two very different novels without telling you just how I’ll measure them. If I give two programmers a complex problem to do and they do it independently, I say I will get two very different programs. I will not get the same or even close. My conclusion from that experiment is, and it's only an intellectual experiment, programming is closer to novel writing than it is to engineering because the engineer is bound by a large number of hard laws of physics and the programmer is much more bound by his mind. Any ingenious thing they can think up just like a novelist. The novelist is bound by their imagination to a great extent. The programmer is bound by their imagination much more than they are bound by hard rules. Therefore it's not so likely that you're going to be able to produce engineered software. It isn't the same problem. It's more like novel writing, as far as I can see.
Now there's lots of ways of improving productivity of programmers. This lead programmers in top-down and bottom-up with this that the other thing. I have only one method that I recommend extensively, it's called think before you write. Now this is something you have great trouble doing. The teacher could preach in a class of programming, think before you write. The students will rush out, sit down at the terminals, start writing the program immediately. Now I had a man working for me for a while. He would wander around the halls, just wandering around, twisting his hair and all this and being sociable. And then after three or four days of wandering around doing nothing, that he was visible, he would sit down, write several thousand lines of code, have them debugged and going. He got far more done per week by not sitting down until everything was clear in his mind and writing it out then. And I have found the same thing. In fact, my recommendation to you is don't write one line of code until you've decided what your acceptance test will be. What tests will you apply to your program to decide it is running correctly? Not that it may be, but what's going to be your acceptance test? Because if you start looking at acceptance tests where all the trouble occurs, you will begin to decide that you better write that program very straightforward and simple so it's easily tested. As a consequence, you'll get there much, much sooner. I promise you, almost always. Now there are exceptions. Some problems we don't know what the problem is and so we start programming to find out what the problem is. And there are a lot of those. And I warn you about those. Take for example the NIKE project. We required a contract that requests for the Defense Department to build a guided missile. The contract didn't specify very much. As we found out what we could do, we could then fill out the details of the contract. We didn't know at the beginning what was reasonable ranges or anything. Your idea that you want to write a definite contact for somebody to do something, is not really a good way to work on open-ended problems. But you don't know what you're doing. You get very bad results. Sometimes programming is a means for finding out what you're trying to do. Now that usually means, when you do that is, after having found out what more or less you're doing you throw the whole thing. Now you understand the problem. You reprogram from scratch and you're better off. But I cannot recommend it too highly. Think before you do any programming and particularly settle yourself how will you decide what you're going to do to accept that the program is running right. It's a very, very powerful thing to do.
Now, I saw a bunch of ones the other day, numbers, about the improvement. Assembler over machine language is said to be two to one. C language over assembler was three to one. Time share to batch was one and a half to one. UNIX to monitor was one and a half to one. System Quality Assurance versus debugging was two to one. Prototyping to top down was not so much. C++ was almost two to one over C, and reuse to redo was one point five to one. The total worked out to be approximately ninety. Let's say it's 100 for sake. Programming from when we started has improved by a factor of 100. Meaning, working reasonable time, in about four months what we would do, you could now do in one day. There would be about 100 working in four months, right? So that's all we've done. Computers have moved from either one operation per second or if you want one for 20 seconds up to a billion, 10 to the ninth. You've only got 100. The situation is really pretty bad. It's pretty bad, indeed. The machines have enormously increased and you, furthermore, believe that parallel machines are further going to increase, but parallel machines are going to put a bigger burden on programming. We desperately need better programming.
So we ask ourselves, can we teach programming? Well let's first look at a few other facts and come down to that. One fact is that programmers differ in productivity more than ten to one. In fact, my friends who form software houses, I've said look, pay your good programmers anything and fire the bad ones. Now you may not get away with firing them, so what you do is you hire them on contract and you pay the guys who deliver on time big sums of money. And those who don't, you don't rehire them. If programmers are more than ten to one, there are times when you could afford to pay the bad programmer to stay home and not come to work, and you'll be ahead. I'm serious.
Well, now we come down to can we teach programming? Well, I liken programming to writing novels. I point out to you the following facts about writing: almost everybody who takes a course in creative writing does not become a great writer. Most great writers in the past did not take courses in creative writing. Can we teach good writing? Yes and no. It's evident we don't do as good a job as we would like to. If you want to become a great novelist, the way is not to start taking creative writing courses. That isn't a way to do it. Does experience help? More years of programming, are you better? Let me ask you the question? Take a bureaucrat in Washington. Is the stuff he writes after 20 years any better than he did when he started? Is experience any good? Does the use of a large number of different languages, make a programmer any good? No. The experienced useful bunch of languages. None of those seemed to make a good programmer. That is not what does the trick. What does? What does make great writers? It is apparently, the ability for the individual to set up a criteria of what they privately consider good programming and criticize themselves and hold themselves to a high standard of writing. Now White, who wrote Strunk and White and was a writer for New Yorker, he was a very good stylist. He points out how many times he failed to follow his own instructions. Good writing is like playing a good game of tennis. You know all the moves but somehow you can't put them together right. Writing is a very hard business. It apparently is, a matter of the individual doing it.
Now I spoke about top-down and bottom-up. I once had lunch with, what were generally considered at that time, two of the best programmers at Bell Labs. We were eating in a restaurant. I asked them, which they did? One guy said, well he started and just sketched out the whole logical structure while putting in two boxes. I was here, here, here, and here. I've got the whole structure going and then he filled in the boxes in any order he felt like. The other guy said, well he started some place and then he expanded out. Now to what extent they were pulling my leg, I don't know. But, in fact, the two guys were rather different. One was a top-down programmer. One was a bottom-up programmer. I'm inclined to believe top-down is better but the evidence is not that wonderfully good that I can say it flatly that this is the best way to do it. The young lady, I spoke of several times, worked for me. I tried to get her to top-down. She couldn't do it. She had to derive from bottom up but she was superb programmer but she started with the inner loop and expanded out. She couldn't start at the top and go down. So I don't know what makes good programmers. But I suggest to you strongly, that experience is not so good nor are teachers of programmers. While at Bell Labs there was a guy named Kernighan who was a good stylist and also was a good writer. And I told him we need a book on programming. What we need are bad examples of good examples. Just like you find in handbooks on English. Well I needled him for a while, nothing happened. I finally took a carton of programming books and took it over to his office and said, here is a bunch of books. You can look at those and see what's wrong. Every bad example which he used in his book came for a book on programming. And held up as a good model. That tells you the professors who teach programming are not necessarily very good programmers. The textbooks would not support good programming. They were provided a large number of very, very hideous examples. One, the best one, is a long program he copies down and says well that's a long program, it must do something. Let's go after it. So he analyzed this and through this and this and this, he finally comes down to the program - about four lines. That's all there is. The whole thing. Several of those are absolutely spectacular at how bad they were and how they didn't do it. And his criteria was quite correct, if the program does not get the right answer it doesn't matter anything else. And some of those wouldn't even get the right answer. What they're supposed to do. And they were in books on programming.
So you see we face a very, very difficult problem. I have compared software with writing. They're not exactly the same but there is a great deal of element of this truth in it. Writing, particularly novel writing, is restricted by your imagination to a great extent. Programming has got a great deal of latitude. Now what I did when I got myself involved in programming for a while, I deliberately adopted engineering restraints. For example, I had made mistakes in counting around when we had to simulate index registers. They weren't in the machines originally. I picked a fixed way of doing it. I always wrote the same way. It had several merits. I didn't make mistakes, but also in scanning a program that block I could recognize immediately because it was always the same way. Never a variation. I had a bunch of other very rigid ones. For example, the moment I read anything in, I printed it out. I was sick and tired of having programs whose answer I had but I didn't know the problem because the parameters hadn't written out. So every time I read a number it immediately was printed out. I made several fixed rules like that and I think I profited greatly by adopting some rigidity.
Now my choice in the loops was very bad. The choice I made, you couldn't do loop no time. Now a guy in numerical analysis doesn't want to do loop no times, but a guy in artificial intelligence frequently wants not to do the loop. So I had picked a bad form. I wasn’t necessarily perfect but I found the adoption of rigid rules for myself was a great help because I could recognize patches of program later on. I tried to, what I told you, adopt internal standards of what was good programming and what was not good programming and tried to hold myself to it. But what happened to me was an unfortunate thing. Just about time FORTRAN was becoming reasonably available, my boss said to me one day, “Hamming you cannot compete with the people working for you. You cannot go on programming.” I protested a little bit, thought about it, and I agreed he was right. I had not to program I knew how to do it but I couldn't practice because my boss was right. You should not compete with people working for you. It's not fair.
When I came here, I no longer had programmers working for me. So I got, the school at that time was issuing some nice little hand programmer calculators to students, and I was asked to teach a course. And so I wrote a book on how to write programs that language and the book is a very nice one. Of course it is long since out of date but it was nice enough. So a friend of mine the other day asked me, did I have any more copies of that manual because he wanted to look at the style in which that manual was written. So I'm inclined to believe that I think it's right to say I know something about programming, that I know something about style, but style programmer is as variable as the styles of writers. I do command top down. I do command someone other things like that, but I admit that there are other ways. You have to find one you like, but it's one thing the program as individual. It's a very different problem when a group undertakes to do the job. Very, very different. A team of programmers is a very different problem than an individual writing programs. And I've had very little experience with that but I can easily see that the group probably needs to get together and agree that they will accept certain restraints in their programming, but don't let those restraints be imposed unless you can write a program which will scan. Does this program obey those rules? If you can't write a program which checks that somebody else’s program is obeying those rules, forget it. Because you haven't got the manpower to check that everybody is following the rules. You have to have the machine check it. Those rules which are easily checkable on a machine are great. Because when later on scanning something, if everybody is using the same rules, that block there and that block there will be immediately identified what it is and then they can orient themselves in the programming. If whimsically there interchanged, one instruction or another in a different order, same block but just order change, it's not so easily recognized. And, in fact, if you interchange one the block of code, you interchange one instruction, and you can cause chaos.
You may remember there was a time, sometime back, when the telephone company was horror. Brought down most of the east coast for a while, so telephony. Remember that. All it was, there was a block of programming and somebody wanted to change a couple O's to speed things up. Well with such a small change they agreed not to go through the three-month routine testing of the program. It crashed. The whole damn East Coast practically. It's not easy when you interchange human instructions to what will happen and the telephone company, to its very great shame, slipped up once and did not follow its own rules about testing because it was so obvious it must be the same.
Well I've told you software is a major problem, it will not go away but it is a problem involving you as humans. The more I study and think about programming the more I understand I'm looking at human beings. I preach to you, in summary, remember write psychological rather than logically. Write so can we follow. Write so that you, five years later, will know what you were doing. Don't do some cute trick. You won't remember. Don't take some advanced some peculiar feature of machine.
On the 650, they asked me which one did I want one delivered. I said I'll take the 11th machine off the production line. I know the first couple have bugs. You'll fix them up. They won't be like other machines. I want to get one so that every other machine of that bunch, if the program runs on my machine it will run on that one. I also took the minimal machine with minimal attachments so that whatever I did would run elsewhere. Getting special attachments on. If you put attachment A followed by B or B followed by A the machine would be wired quite differently inside. They may behave differently. You can't necessarily depend upon these things. So you want to be very careful when you get involved with machines. Now we're doing better but I think you know about the Pentium chip. You've heard about that. We still can't do things right. So I leave it to you this very important problem it's extremely expensive and it's going to get more expensive. Humans are going to become more expensive. Machines are going to become cheaper, so the problem of programming is central. And we'll take up something next time. I'll take up applications and we'll go on to AI which really it bears on this question of how people think and such other things. So we'll see you.