Or, Deathmatch: ZX-80 BASIC vs. Python
The most productive programming environment I’ve ever experienced was the Sinclair ZX-80. Back in 1981, after years of begging and pleading, my parents finally succumbed and bought me my first computer. (They’d already bought me my first programmable calculator, itself a Sinclair rebadged by Radio Shack. I’d played with an HP65 for an afternoon back in 1977 and been hooked ever since.)
Let me describe the ZX-80. It had a Z80 cpu (hence its name) running at 1MHz. It had a 4kB ROM which included an integer BASIC runtime. (I eventually got the ZX-81 ROM which upped it to 8kB and floating point.) And it had 1kB of onboard RAM, but mine was maxed out with a 16kB expansion “blob”, which stuck out the back like a tumor. Physically, the computer was a thin plastic box with a bulge for the circuit board and a membrane keyboard with BASIC commands and graphic block symbols festooned over the characters.
How can I claim that this was the most productive programming environment I’ve ever experienced?
Well, I’d played Adventure on the DEC-10 at the local university where my father taught, and a very weak clone on the Apple II. Adventure was pretty lame, but while the DEC version had a simple inventory system, the Apple II version simply involved navigating the maze. While I thought both had potential, they scarcely qualified as games and weren’t much fun.
I thought I could do better: I was seventeen, with little training in programming and none in computer science, and I did not know what the word “parser” meant.
I sat down at my ZX-80 with its ZX-81 ROM and 16kB of RAM upgrades and I wrote that sucker in a single afternoon. I can’t say it was bug free but it was pretty solid. I don’t recall it having any significant bugs. But I do know that I wrote the code down by hand (the ZX-80 had no printing capability, and its only storage was audio cassette which wasn’t even compatible between ROM versions let alone other systems) in order to port it to the Apple II at school. (My game had maxed out my system’s memory, which in practice meant that I couldn’t make the virtual world bigger than about twenty rooms.)
It took me over three months to get the same logic working on the Apple II, and the Apple II version was never as robust as the original (although admittedly it had more content and more features). Remember, I’d figured all of this out in an afternoon, and had a working solution.
So, what I implemented was: a text adventure game with a data-driven content model, simple combat with a variety of monsters, a simple inventory system, and a “natural language” text parser (better than Adventure, nowhere near as good as Zork — which I wouldn’t see in action until I got to college). Items could be “dropped” in locations. Items could be “equipped”. Your equipment impacted combat.
Why was the ZX-80 programming environment so productive?
Here’s a list of things it definitely lacked:
- Encapsulation All variables were globals. They could be strings or ints. No named procedures — remember GOTO and GOSUB? That’s what it had.
- Powerful iterators Does FOR..NEXT count?
- Object-oriented programming. Um, no.
- Functional programming Closures, Lambdas, Tail Recursion? No.
- Less typing Kind of. Although most keywords could be entered by single or double keystroke macros, but this was more than offset by the ZX-80’s membrane keyboard.
Here’s what it did have:
- Language-Savvy Editor the editor tokenized your code as you typed it, could figure out from context what kind of thing you were entering (imperative keyword, function keyword, variable name, literal, etc.) and would tell you if your code was currently legal and would not allow illegal statements to be entered. This didn’t eliminate logical errors in your program design, but it prevented trivial mistakes (“missing semicolons”) from ever occurring.
- Very Good String Manipulation the Apple II had pretty decent string manipulation for the time (i.e. it had LEFT, RIGHT, and MID), but the ZX-80 simply let you slice strings (much like
Substrand similar commands in modern languages).
- Good Documentation the computer came with a book that contained a list of all the commands and explanations of what they did.
- No lowercase characters case sensitive programming languages and string matching are simply a net loss to everyone. By all means preserve case and use capitalization conventions to make stuff more readable, but don’t require people to guess whether it’s Math.Sin or Math.sin or math.sin.
This article started out as a rant against Java in general and the assertion by Ben Horowitz in a debate in the Economist that programmers were ten times more productive today than during the last tech bubble. (Not that this assertion needs repudiation; every programmer I’ve pointed it out to has found it hilarious.)
Do you know what I like? I like programming environments where you can get a big book that explains all the commands that are available. Maybe not all the commands, but say all the main commands. If there’s extra domain-specific functionality, it’s OK if there’s a separate book or chapter covering each specific domain. E.g. You might have a whole bunch of stuff dealing with files in the book on File System Programming.
You know what else I like? Not burying the lead. What’s the difference between system.file.io.read and system.file.io.write? They’re very, very different things and yet they look very, very similar. I made both up, but they bear a striking resemblance to every single fucking thing in a programming language called Java.
You know yet another thing I like? I like global variables. I don’t think they should be used for everything, but — and this will be a little shocking to some of you — you can use them for everything. We know that because in Turing machines all variables are global. Do you know what you can’t use for everything? Local variables. Here’s the announcement that triggered my need to rant against Java — the Google Singleton Detector.
In essence, it’s a tool for detecting patterns of global state in Java programs. Why do these patterns exist? Because Java has “no globals”. In other words, when you decide something useful is a “problem” and prevent programmers from using it they will implement a workaround and now you have two problems. What’s worse, the second problem is likely to take many forms and be disguised as something innocuous. Indeed, Singletons are a “design pattern” — i.e. something cool that programmers should do, not something evil like global variables. But in fact, singletons are simply wrappers for global state.
But this isn’t a rant against Java. It’s a rant about better, smarter development tools.
How can we recapture the benefits of the ZX-80?
There’s no question that there are huge wins in modern languages. I like every single thing about Python — for example — except its execution speed and the use of semantic indentation. Because it is interpreted it is not only possible but “easy” for a hypothetical IDE to know enough about each line of code, as it is typed, whether that line of code is currently legal and what kinds of things the programmer may enter at any given moment. I used to think semantic indentation was a Bad Idea because it led to lots of painful debugging, but now I realize it’s a problem of Bad Tools.
If someone wrote a Python IDE that was as smart about Python as the ZX-80 was about its weird version of BASIC it could be wonderful. (Again, I ask the question, if Python or Ruby on Rails are such great languages, why haven’t great tools been written for coding with them, in them? Writing web development frameworks is easy. Write a decent editor or IDE.) Add a mature PyPy back-end and a nice cross-platform GUI library. Give me one-click cross-platform single file executables. (Realbasic used to do it, and — rumor has it — may do so again soon.) Nirvana.
Hmm, Andrew Barry, are you listening?
[Image credit: Wikipedia.]