Picaxe and Parallax: Crimes Against Humanity

October 5, 2014

That's a pretty strong title. And of course it is mostly hype. But I am strongly against many of Picaxe (Revolution Education) and Parallax products. The Parallax Basic Stamp products, and the copy-cat products like Pic Basic and Rev Ed's Picaxe products, are doing as much harm as good for the future of society. Let me explain why.

Computers and Society

Our modern society is completely dependent on computer technology. The existence of this document and the fact you have access to it is a testament to that. Almost all of our communications, our finances, our education, our transportation, all depend heavily on computer technology. The computer hardware has advanced drastically in the last 30 years or so. The power and ubiquity are simply amazing. When I was a kid, a common dream was to have, in some far away time and fictional place, something like a Dick Tracy phone. Now, we have far surpassed that. There are two main technological fields driving these advances: computer hardware and software.

Hardware vs Software

Hardware and software are closely related, but different enough to be separate branches of science and technology in daily work. The hardware continues to advance more or less as Moore's Law predicted 50 years ago. From a dozen or so transistors on a chip (integrated circuit) 60 years ago, to a billion or more now, the march of technology in the hardware field is almost unbelievable. It is huge and complex, but mostly straightforward to design. There are many tools that will take a collection of building blocks, put them together as the engineer desires, and make larger building blocks out of them. There are standards that make this simpler than it otherwise would be. It certainly isn't easy, but mostly it is manageable. When the inevitable bugs creep in, it makes headlines. Hardware is expensive. To make a new chip requires often millions of dollars in Research and Development, and then the use of a multi-billion dollar plant to actually manufacture. The companies making them take great pains, using simulations and other tools, to make sure the design is as close to right as possible before commiting to have it manufactured. The cost of mistakes is enormous, especially if they ship in a product. The Pentium bug of the mid 90s was a prime example.

Software, on the other hand, seems to be very simple. It is certainly cheap and easy to produce. That's a big part of the problem. Any kid with a PC and an Internet connection can download Visual Studio Express or Eclipse and start writing software. There are hundreds, probably thousands, of tutorials on the web to teach programming. Modern tools, like Visual Studio, will create a good portion of the application for you. (With really crappy code, by the way). It isn't hard to learn the basics of programming. And in a short time they can have their programs on the web, maybe on the Android application site. All at zero cost. The web is full of stuff like that. No engineering, no knowledge of software engineering best practices. Just hack away until it seems to work. Most of the time. Or some of the time. And release it into the wild. The demand for software has created a rich environment for that sort of activity, and overall the quality of software is rather poor.

Software is Hard

None of that is to slight anyone (kid or adult) that learns to program that way. Even if they release the programs into the wild of the Internet. I think it is great. Programming is important to our future. The hardware is great, but it really doesn't do much without some software. And many of those people, especially the kids, will end up as the software engineers that create our future. That is how I first learned to program. And I am in good company. People like Bill Gates did much the same. Programming is fun. It's addictive. It's satisfying making a machine do your bidding. And it is important for our future. Unless you've been living on Jupiter the last ten years (Mars has probably heard, thanks to the rovers), you have seen the push on STEM education. There is a shortage of engineers in the US and many other places. Especially software engineers. And many of the ones that exist are, uh, less than stellar. I have interviewed some that amazed me they had finished school. And these were the ones that made it through the resume cull and phone interviews. Companies are being forced to do all sorts of things to attract the talented ones. Take a look at what Google and other similar companies offer their employees. Microsoft hires some of the best, too. But take a look at the products from these big companies who go the extra mile to get the best talent: they still have visible bugs!

So what happens to those less than stellar software engineers? Well, there is a shortage, so they get hired by someone. If Google and Microsoft are churning out bugs with the best talent, what do you think these other companies are producing? What companies write your (and your bank's!) financial applications? Who are they hiring? What quality is their software? How many big companies have had their customer databases compromised? Apple. Sony. Home Depot. Target. That's just a few I can think of off the top of my head. Software is hard.

Having said that, I feel it is important to teach programming as best we know how. Fifty years ago computer scientists started pushing for better programming practices. Fortran was recognized as bad, and new languages were created to help with "structured" programming practices. New ways to program better are being created all the time. We should pay attention and teach new programmers the best ways we know, and encourage them not to use old, outdated, known bad methods.

Programming is a Mindset

When the discussion of programming comes up, people often tend to demonstrate their programming ability by telling all the programming languages they use. Unfortunately, that says very little about their programming ability. Programming is about problem solving. There are different paradigms, or approaches, to solving most any problem. One's ability to program is shown by how well they solve problems. A program to solve any particular problem can be written in any language, using any paradigm. However, different languages are more suited to certain paradigms. Using a language for a paradigm it isn't designed or suited for can be extremely painful, but it can be done. It is actually rather common to use some object-oriented techniques with C, which is not an object oriented language. The results are quite clumsy.

So why does the language matter? Because to effectively use the language as it was intended and be productive, you have to follow the paradigm it was designed for. Each individual language will support certain features that are designed for the paradigm it is intended for. To be effective, you have to place your mind into the mindset of that paradigm. The language "guides" your thought process to some extent. Forcing a language to another paradigm can be done, but it is not easy or natural. Think of running a marathon in work boots. In short, if all you have is a hammer, everything looks like a nail.

Enter Beginners All Purpose Symbolic Instruction Code

In the early 50s, computers were still quite new and rare. Programming techniques were still being figured out, but the future held great promise. All programming was done in machine language. Assemblers were just being developed. Some programmers realized they kept writing the same program pieces over and over. So they created a way of putting those pieces into libraries for reuse in many programs. The next step was to write another program that would allow you to "program" with "formulas" as they would be written, and translate that into a program that used those library routines. Then, since computers are useless without being able to make decisions and change the flow of control, various means of "branching" were added. Before long, they had created a "high level language" that "compiled" formulas into machine code. They called it "Formula Translation," or just FORTRAN for short.

By the early 60s FORTRAN reigned supreme in science and engineering. Computers were more common and many universities were teaching science and engineering students how to use them, which at the time meant how to program them. But Kemeny and Kurtz decided Fortran was more complicated than necessary, and decided to create a new language, based on Fortran but simpler, to teach introductory progamming.

The new langauge was stripped down. It was made as simple as possible. Now, take this in perspective. Fortran of the early 60s was a VERY simple language compared to modern languages, and this new language was made even simpler. But it still had much of the flavor of its inspiration Fortran. Fortran was one of the first high level languages, and it was created before good programming practices had been devised. By the early and mid 60s many computer scientists were realizing the dangers of the Fortran programming model. But users were high on the power of the computer, and too inexperienced to know better, so they kept using it more and more. It didn't help that Fortran was the "standard" language and often the only one available on the computers they had access to. The new beginners' language brought along most of the bad parts of Fortan and to some degree made things even worse. But it worked, and was popular, and most important to our story, was simple. The new language was named, in the style of the time, "Beginners' All Purpose Symbolic Instruction Code," or BASIC.

Over the next ten years or so, BASIC became very popular. It was extended in all sorts of directions by many companies for their own computers and uses. There was no real standard. Everyone did things differently. But it had a few traits that were very common. Most implementations were interpreted (see below), used GOSUB and GOTO instead of proper procedures/functions/subroutines, required line numbers on ever line, had only global variables (no local variables), and had minimal support for "structured" programming that was becoming the paradigm of choice.

How BASIC Works, and Why

Knowing how a typical implementation of BASIC works, and why it is built that way, will be helpful in understanding the rest of this discussion. Now, it must be said that there are literally hundreds (thousands?) of implementations of BASIC, and they are done in lots of different ways. The ones we are interested in fall into a certain category, which was made popular in the mid 70s when personal computers appeared. The new personal computers were very simple and had minimal resources, so they were very constrained in what they could support. It was something of a miracle that they could run any type of high level language, and I hold nothing against Microsoft or the other companies and individuals for producing the type of BASICs they did: it was really all that was reasonable at the time.

A computer can only execute programs in "machine language." The machine language is specific to a certain (type of) processor and is different on different machines. It is very low-level, and typically has very simple "instructions" that do very basic things like move a value from one place to another, add two values, "and" one value with another, and transfer control to a different place in the program, possibly based on some condition, like a certain value being present. Machine language is rather tedious and time consuming, so we use "high-level languages, like BASIC, C, or Python. But the computer doesn't "know" how to run programs in those languages: they must somehow be translated to machine language.

There are two basic methods of translating: interpreting and compiling. A compiler goes through the entire program in the high-level language and converts all of it to machine language at once. After all of it has been converted, it can be run directly. Compiling only has to be done once, unless changes are made to the program. From then on it can be run as many times as needed, directly executed on the processor, without any conversion steps. Often, with a good quality compiler, the resulting program will be faster even than the equivalent program written in assembly (machine) language by a human. The other method, interpreting, "converts" the program to machine language as it is running. Usually, it never actually produces any machine language program, but instead has a "library" of machine language programs built in. As the interpreter scans through the program "running" it, it looks up each command of the high-level language and runs the appropriate library routine to perform that action. The process is normally much slower than running a machine language program directly. In addition, it has to be done every time the program runs. Not only that, if there is a loop in the program the code within the loop must be re-interpreted each time through the loop. It is not unusual at all for an interpreted program to be 1000 times slower than an equivalent compiled or machine language program.

Almost any language can be either interpreted or compiled, but often any one language is most often done one way or the other. C, C++, Ada, and others are almost always compiled. BASIC is most often interpreted. In some cases, arguments arise about whether a language is interpreted or compiled, ie Java. Why? Typically because the language is compiled to a machine language for a machine that doesn't really exist (sometimes called bytecode), then the resulting program is interpreted, much as a simulator for one computer running on another. There are more variations, but these three cases cover most of what's important. If you are in the mood for a fight, tell a Java programmer you don't like Java because it is interpreted.

As I mentioned, BASIC is most often interpreted. The ones we are focused on (BASIC Stamps, Picaxe, early Microsoft and other personal computer versions, and similar) are. But if interpreting is so slow, why do we use them at all? It turns out there are some very good reasons, and some not so good reasons.

To quote David Gries in the classic but dated "Compiler Construction For Digital Computers,": "Interpretation lends itself to an educational environment, where most of the time is spent debugging source programs."
The process of compiling usually throws away a lot of information that is useful when debugging. An interpreter necessarily keeps most of that information (ie variable names, the source code, etc) and has easy access to it while running, since it needs it to interpret the program. So ease of debugging is a big plus for an interpreter.

When using a compiler, one must go through the edit, compile, link, and maybe some other steps, then run. The compile and link steps may be time consuming and may work for a while then produce a cryptic error message. With most interpreters, especially BASIC, you simply edit and run. Typically, the editor will not allow some syntax errors, and others will be much easier to find at runtime. The development process is speeded greatly. Interpreters are much easier to develop with.

Another reason is space. The process of compiling takes a lot of memory in one form or another. There must be room for the source code, the compiled program, and various versions of an "internal form" of the program, all at the same time. On computers of the late 70s, there often simply wasn't enough memory available to run a compiler. The interpreters used then (Microsoft BASIC and similar) simply converted each line as it was typed in to a "tokenized" form, with each word (ie "IF", "GOTO", "GOSUB", "THEN", etc) represented by a single byte. There was no input held in memory, the "tokenized" form was all that needed to be stored. That made them very space efficient. The tokenized form also made the code that scanned and interpreted it much simpler, since it only had to recognize a single byte instead of a variable length string of characters. That again saved space (and time), and was a huge advantage on those computers. It may be an advantage on some of the microcontrollers with BASIC today. Then again, it may not.

Another reason to use an interpreter is that it is easier to write and get working than a compiler. That may have been an advantage to someone trying to create something in 1977. Today, it is nothing more than an excuse in a commercial product.

So, let's walk through the process of interpreting a BASIC program. First, the user types in the code. In old personal computer BASICs each line would be tokenized when [ENTER] was pressed, and syntax errors on that line reported. With most newer versions, the entire program will be tokenized and checked after it is complete and the programmer tries to run it.

Once a syntactically correct program is tokenized and stored, the actual interpreter portion begins scanning at the first token. The token is examined and looked up in a table. The table points to a subroutine to run to handle that token. If any math expressions are expected, the subroutine for that token extracts the operands and operators from the list of tokens and performs the indicated operations. The results are stored or compared as needed, then the next token is scanned and interpreted. If a branch (GOTO, GOSUB, IF, THEN, etc) needs to change the current location of the program, that is done as well. The fetch token, interpret, repeat cycle goes on until the program completes or encounters an error. All in all it is pretty simple and relatively efficient, especially with space. Small and simple were the necessity in 1977. With many small microcontrollers today, like a PIC, it would seem to be the rule now. But we will come back to that.

Microsoft, Parallax, and the CopyCats

We have looked a little at how and why early microcomputer BASICS worked. Microsoft BASIC was by far the most common, but there were others that were quite popular. Almost all of them worked as I described above, for the reasons I listed. It was, to some extent, almost a miracle that anything could be made to work on those slow machines with only 4K (4096 bytes) of RAM. Not four megabytes. Not four gigabytes. Four kilobytes -- 4096.

Those early micro BASICs were very limited by necessity. They had much less capability than most of the minicomputer and mainframe BASICs of the same time period. But they worked, and were often the only alternative to machine/assembly language on the small computers of the day. The language was terrible looking back, but we didn't know any better and were glad it existed.

Around the same time, in the late 70s, the microcontroller as it currently exists began to appear. These were small and simple microprocessors intended to be used for controlling devices rather than as the CPU of a computer. They had part numbers like 8048, 8051, 8073, and others. They typically had a CPU, I/O, some peripherals, some RAM (64 to 256 bytes), and often ROM (not flash or EEPROM, and usually not even EPROM) on board. They were billed as single chip solutions and were very popular. But generally they had to be programmed in assembly language. And since the processors were so simple, that was often rathe difficult. The popularity and ease of use of BASIC made it attractive for use on these small processors when being used for simple control functions. And some of these chips with very simple BASIC interpreters programmed into their ROM began to appear. The two biggest were the 8073 SC/MP from National Semiconductor and the 8052-Basic From Intel.

These chips, especially the 8052 were rather popular. The 8052 continues to be, even though I believe it is out of production. You can download the binary file for the BASIC in the 8052, buy a modern version of the 8052 with flash memory, and program the interpreter into it. These solutions were rather unique and mostly unmatched in today's market. They had the entire interpreter on board. They did not need a computer to program them. All they needed was some sort of serial terminal to enter the program into their memory. That is rather different from the Basic Stamps and Picaxes that came later. Those need a computer running "editor" software that does some processing before downloading.

Now that we have escaped the 70s, let's move to the Basic Stamps.

Why the Picaxe Family is Bad

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.
Edsger W. Dijkstra

Before I start bashing the Picaxe and friends too bad, let me say that I think the BASIC Stamp, the Picaxe, and the other similar hobby-oriented development systems have done a lot of good. They have made it possible for people to do things they likely would not have been able to do otherwise. Many people have created some really nice projects with them. I am sure they have brought people into careers they would not have gone into without an introduction to these products. And, of course, they are fun! OK. Nice time is over. Let the bashing commence!

Around 1959 or so, a new programming language very different from Fortran was invented. Instead of being designed ad-hoc as features were deemed to be needed, it was designed from the ground up to make programs better. Why? It had already, by 1959, been realized that the way Fortran encouraged (and demanded!) programs to be written was bad. A few of the characteristics that made Fortran bad: