Now we’ve got a concurrent language and parallel processes and inside these processes we’re doing full Prolog with backtracking and all that kind of stuff. So the Prolog became very deterministic with cuts everywhere to stop it from backtracking.
Seibeclass="underline" Where the irreversible things would be sending messages to other processes?
Armstrong: Yes. But it’s just a function call and maybe not of the function that fires the rockets but one that calls something else that calls something else that calls it so it’s just a pain kind of trying to keep these two worlds separate. So the code you wrote inside a process became more and more functional, sort of a dialect of Prolog which was a functional subset. And so if it’s a functional subset, might as well make it completely functional.
Seibeclass="underline" Yet Erlang is pretty different from most functional languages these days in being dynamically typed. Do you feel like part of the functional language community?
Armstrong: Oh yes. When we go to functional programming conferences, I suppose we argue about our differences. We argue about eager evaluation and lazy evaluation. We argue about dynamic type systems and static type systems. But despite everything the central core of functional programming is the idea of nonmutable state—that x isn’t the name of a location in memory; it’s a value. So it can’t change. We say x equals three and you can’t change it thereafter. All these different communities say that has enormous benefits for understanding your program and for parallelizing your program and for debugging your program. Then there are functional languages with dynamic type systems like Erlang and functional languages with static type systems and they’ve both got their good and bad points.
It’d be really nice to have the benefits of a static type system in Erlang. Maybe in certain places we could annotate programs to make the types more explicit so the compiler can derive the types and generate much better code.
Then the static type people say, “Well, we really rather like the benefits of dynamic types when we’re marshaling data structures.” We can’t send an arbitrary program down a wire and reconstruct it at the other end because we need to know the type. And we have—Cardelli called it a system that’s permanently inconsistent. We have systems that are growing and changing all the time, where the parts may be temporarily inconsistent. And as I change the code in a system, it’s not atomic. Some of the nodes change, others don’t. They talk to each other—at certain times they’re consistent. At other times—when we go over a communication boundary—do we trust that the boundary is correct? They might fib. So we need to check certain stuff.
Seibeclass="underline" So early on you earned your beer by debugging other people’s programs. Why do you think you were such a good debugger?
Armstrong: Well, I enjoyed debugging. At this point in the program you print out a few variables and things to see what’s going on and they’re all according to what you expect. And at this point in the program it’s right. And somewhere later it’s wrong. So you look halfway in between—it’s either right or wrong and you just do this interval halving. Provided you can reproduce an error. Errors that are nonreproducible, that’s pretty difficult to debug. But they weren’t giving me that. They were giving me reproducible errors. So just carry on halving until you find it. You must ultimately find it.
Seibeclass="underline" So do you think you just had a more systematic view?
Armstrong: Yeah, they gave up. I don’t know why—I couldn’t really understand why they couldn’t debug programs. I mean, do you think debugging is difficult? I don’t. You just stop it and slow it down. I mean, I’m just talking about batch Fortran.
OK, debugging real-time systems or garbage collectors—I remember once Erlang crashed—it was early days—and it crashed just after I’d started it. I was just typing something. It had built in sort of Emacsy commands into the shell. And I typed erl to start it and you get into a read-eval-print loop. And I’d typed about four or five characters and made a spelling mistake. And then I backed the cursor a couple of times and corrected it and it crashed with a garbage collection error. And I knew that’s a deep, deep, error. And I thought, “Can I remember exactly what did I type in?” Because it was only about 12 characters or something. I restarted and typed and it didn’t crash. And I sat there for like an hour and a half trying probably a hundred different things. Then it crashed again! Then I wrote it down. Then I could debug it.
Seibeclass="underline" What are the techniques that you use there? Print statements?
Armstrong: Print statements. The great gods of programming said, “Thou shalt put printf statements in your program at the point where you think it’s gone wrong, recompile, and run it.”
Then there’s—I don’t know if I read it somewhere or if I invented it myself—Joe’s Law of Debugging, which is that all errors will be plus/minus three statements of the place you last changed the program. When I worked at the Swedish Space Corporation my boss was a hardware guy. We were up at Esrange, the rocket-launching site and satellite-tracking station in the north. And one time he was banging his head, debugging some bug in the hardware, plugging in oscilloscopes, and changing things. And I said, “Oh, can I help?” And he said, “No Joe, you can’t help here—this is hardware.” And I said, “Yeah, but it must be like software—the bug will be pretty near to the last change you made to the hardware.” And he went, “I changed a capacitor. You’re a genius!” He’d replaced one capacitor with a bigger capacitor and he unsoldered it and put the original one back and it worked. It’s the same everywhere. You fix your car and it goes wrong—it’s the last thing you did. You changed something—you just have to remember what it was. It’s true with everything.
Seibeclass="underline" So have you ever proved any of your programs correct? Has that kind of formalism ever appealed to you?
Armstrong: Yes and no. I’ve manipulated programs algebraically to just show that they were equivalent. Haven’t really gone into theorem proving as such. I did a course in denotational semantics and things like that. I remember giving up. The exercise was given: let x = 3 in let y = 4 in xplus y show that the eager evaluation scheme given by the equations foo and the lazy evaluation scheme given by the equations bar, both evaluate to seven.
Fourteen pages of lemmas and things later I thought, “Hang on—x is three, y is four, x plus y; yeah seven.” At the time I was writing the Erlang compiler. If it took lots of pages to prove that three plus four is seven then the proof that my compiler was in any sense correct would have been thousands and thousands of pages.
Seibeclass="underline" Do you prefer to work alone or on a team?
Armstrong: I like a workplace of teams, if you see what I mean. I’m not antisocial. But I just like programming by myself. Certainly I like collaborating with people in the sense of discussing problems with them. I always thought the coffee break that you have when you got to work and out came all the ideas that you’d had on your walk to work was very valuable. You get a lot of insights then. Good to thrash your ideas out in front of the crowd. You’re put in a position of explaining your ideas which, for me, moves them from one part of my brain to another part. Often when you explain things then you understand them better.